aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib')
-rw-r--r--contrib/llvm-project/clang/lib/AST/ASTImporter.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/AST/Decl.cpp24
-rw-r--r--contrib/llvm-project/clang/lib/AST/DeclBase.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/AST/DeclCXX.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp8
-rw-r--r--contrib/llvm-project/clang/lib/AST/ExprConstant.cpp6
-rw-r--r--contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp13
-rw-r--r--contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp6
-rw-r--r--contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp83
-rw-r--r--contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp11
-rw-r--r--contrib/llvm-project/clang/lib/Basic/MakeSupport.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Basic/NoSanitizeList.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/Basic/Sarif.cpp389
-rw-r--r--contrib/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp1
-rw-r--r--contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h4
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp1
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGCall.h3
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp185
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp25
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGObjCRuntime.h3
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp7
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp23
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp137
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h49
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/SwiftCallingConv.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp14
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h4
-rw-r--r--contrib/llvm-project/clang/lib/Driver/Driver.cpp36
-rw-r--r--contrib/llvm-project/clang/lib/Driver/Multilib.cpp7
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChain.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp10
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp12
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp103
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h6
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp30
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp16
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp11
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp1
-rw-r--r--contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp11
-rw-r--r--contrib/llvm-project/clang/lib/Format/Format.cpp39
-rw-r--r--contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp13
-rw-r--r--contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp21
-rw-r--r--contrib/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Headers/__clang_cuda_intrinsics.h8
-rw-r--r--contrib/llvm-project/clang/lib/Headers/ppc_wrappers/emmintrin.h7
-rw-r--r--contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mm_malloc.h3
-rw-r--r--contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mmintrin.h7
-rw-r--r--contrib/llvm-project/clang/lib/Headers/ppc_wrappers/pmmintrin.h7
-rw-r--r--contrib/llvm-project/clang/lib/Headers/ppc_wrappers/smmintrin.h7
-rw-r--r--contrib/llvm-project/clang/lib/Headers/ppc_wrappers/tmmintrin.h7
-rw-r--r--contrib/llvm-project/clang/lib/Headers/ppc_wrappers/xmmintrin.h7
-rw-r--r--contrib/llvm-project/clang/lib/Headers/x86gprintrin.h28
-rw-r--r--contrib/llvm-project/clang/lib/Lex/Lexer.cpp6
-rw-r--r--contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp6
-rw-r--r--contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp29
-rw-r--r--contrib/llvm-project/clang/lib/Parse/ParseAST.cpp23
-rw-r--r--contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp15
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaCUDA.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp49
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp72
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp37
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp11
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp16
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp15
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaModule.cpp10
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp6
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaType.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp502
-rw-r--r--contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp3
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp60
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp156
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp77
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp61
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp4
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp133
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp870
-rw-r--r--contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp10
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp7
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp57
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/Syntax/ComputeReplacements.cpp37
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp5
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/Syntax/Nodes.cpp2
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp34
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp25
-rw-r--r--contrib/llvm-project/clang/lib/Tooling/Syntax/Tree.cpp52
106 files changed, 2585 insertions, 1290 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp
index 73c3f02e67a8..f7e7b73d1218 100644
--- a/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp
+++ b/contrib/llvm-project/clang/lib/AST/ASTImporter.cpp
@@ -3109,6 +3109,11 @@ Error ASTNodeImporter::ImportTemplateInformation(
case FunctionDecl::TK_FunctionTemplate:
return Error::success();
+ case FunctionDecl::TK_DependentNonTemplate:
+ if (Expected<FunctionDecl *> InstFDOrErr =
+ import(FromFD->getInstantiatedFromDecl()))
+ ToFD->setInstantiatedFromDecl(*InstFDOrErr);
+ return Error::success();
case FunctionDecl::TK_MemberSpecialization: {
TemplateSpecializationKind TSK = FromFD->getTemplateSpecializationKind();
diff --git a/contrib/llvm-project/clang/lib/AST/Decl.cpp b/contrib/llvm-project/clang/lib/AST/Decl.cpp
index 68a9dca7d1f8..8580cc639d2d 100644
--- a/contrib/llvm-project/clang/lib/AST/Decl.cpp
+++ b/contrib/llvm-project/clang/lib/AST/Decl.cpp
@@ -3717,8 +3717,13 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
if (TemplateOrSpecialization.isNull())
return TK_NonTemplate;
- if (TemplateOrSpecialization.is<FunctionTemplateDecl *>())
+ if (const auto *ND = TemplateOrSpecialization.dyn_cast<NamedDecl *>()) {
+ if (isa<FunctionDecl>(ND))
+ return TK_DependentNonTemplate;
+ assert(isa<FunctionTemplateDecl>(ND) &&
+ "No other valid types in NamedDecl");
return TK_FunctionTemplate;
+ }
if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
return TK_MemberSpecialization;
if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
@@ -3759,15 +3764,28 @@ FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
}
FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
- return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>();
+ return dyn_cast_or_null<FunctionTemplateDecl>(
+ TemplateOrSpecialization.dyn_cast<NamedDecl *>());
}
-void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
+void FunctionDecl::setDescribedFunctionTemplate(
+ FunctionTemplateDecl *Template) {
assert(TemplateOrSpecialization.isNull() &&
"Member function is already a specialization");
TemplateOrSpecialization = Template;
}
+void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
+ assert(TemplateOrSpecialization.isNull() &&
+ "Function is already a specialization");
+ TemplateOrSpecialization = FD;
+}
+
+FunctionDecl *FunctionDecl::getInstantiatedFromDecl() const {
+ return dyn_cast_or_null<FunctionDecl>(
+ TemplateOrSpecialization.dyn_cast<NamedDecl *>());
+}
+
bool FunctionDecl::isImplicitlyInstantiable() const {
// If the function is invalid, it can't be implicitly instantiated.
if (isInvalidDecl())
diff --git a/contrib/llvm-project/clang/lib/AST/DeclBase.cpp b/contrib/llvm-project/clang/lib/AST/DeclBase.cpp
index 13dd6da3f24f..d12330de1500 100644
--- a/contrib/llvm-project/clang/lib/AST/DeclBase.cpp
+++ b/contrib/llvm-project/clang/lib/AST/DeclBase.cpp
@@ -283,8 +283,9 @@ unsigned Decl::getTemplateDepth() const {
return cast<Decl>(DC)->getTemplateDepth();
}
-const DeclContext *Decl::getParentFunctionOrMethod() const {
- for (const DeclContext *DC = getDeclContext();
+const DeclContext *Decl::getParentFunctionOrMethod(bool LexicalParent) const {
+ for (const DeclContext *DC = LexicalParent ? getLexicalDeclContext()
+ : getDeclContext();
DC && !DC->isTranslationUnit() && !DC->isNamespace();
DC = DC->getParent())
if (DC->isFunctionOrMethod())
diff --git a/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp b/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp
index 6fc9a86bc3cf..c307cbe02ecf 100644
--- a/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp
+++ b/contrib/llvm-project/clang/lib/AST/DeclCXX.cpp
@@ -2410,7 +2410,7 @@ bool CXXMethodDecl::isMoveAssignmentOperator() const {
return false;
QualType ParamType = getParamDecl(0)->getType();
- if (!isa<RValueReferenceType>(ParamType))
+ if (!ParamType->isRValueReferenceType())
return false;
ParamType = ParamType->getPointeeType();
diff --git a/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp b/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp
index 3f04d9b4073e..b041e2a67e95 100644
--- a/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp
+++ b/contrib/llvm-project/clang/lib/AST/DeclPrinter.cpp
@@ -1007,10 +1007,10 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
}
}
- if (auto *Def = D->getDefinition()) {
- if (D->hasAttr<FinalAttr>()) {
- Out << " final";
- }
+ if (D->hasDefinition()) {
+ if (D->hasAttr<FinalAttr>()) {
+ Out << " final";
+ }
}
if (D->isCompleteDefinition()) {
diff --git a/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp b/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp
index 40e044534f0c..cd14ff4fb970 100644
--- a/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm-project/clang/lib/AST/ExprConstant.cpp
@@ -11595,9 +11595,15 @@ static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) {
// conservative with the last element in structs (if it's an array), so our
// current behavior is more compatible than an explicit list approach would
// be.
+ int StrictFlexArraysLevel = Ctx.getLangOpts().StrictFlexArrays;
return LVal.InvalidBase &&
Designator.Entries.size() == Designator.MostDerivedPathLength &&
Designator.MostDerivedIsArrayElement &&
+ (Designator.isMostDerivedAnUnsizedArray() ||
+ Designator.getMostDerivedArraySize() == 0 ||
+ (Designator.getMostDerivedArraySize() == 1 &&
+ StrictFlexArraysLevel < 2) ||
+ StrictFlexArraysLevel == 0) &&
isDesignatorAtObjectEnd(Ctx, LVal);
}
diff --git a/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp b/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp
index 79e9fa6ab86f..22643d4edbec 100644
--- a/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp
+++ b/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp
@@ -1720,6 +1720,9 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) {
}
}
+ if (!D->isInlineSpecified() && D->isInlined()) {
+ OS << " implicit-inline";
+ }
// Since NumParams comes from the FunctionProtoType of the FunctionDecl and
// the Params are set later, it is possible for a dump during debugging to
// encounter a FunctionDecl that has been created but hasn't been assigned
diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
index cd87e87a6aca..5105999741e6 100644
--- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -14,7 +14,9 @@
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Analysis/FlowSensitive/DebugSupport.h"
#include "clang/Analysis/FlowSensitive/Value.h"
+#include "llvm/Support/Debug.h"
#include <cassert>
#include <memory>
#include <utility>
@@ -293,6 +295,17 @@ BoolValue &DataflowAnalysisContext::buildAndSubstituteFlowConditionWithCache(
return substituteBoolValue(*ConstraintsIT->second, SubstitutionsCache);
}
+void DataflowAnalysisContext::dumpFlowCondition(AtomicBoolValue &Token) {
+ llvm::DenseSet<BoolValue *> Constraints = {&Token};
+ llvm::DenseSet<AtomicBoolValue *> VisitedTokens;
+ addTransitiveFlowConditionConstraints(Token, Constraints, VisitedTokens);
+
+ llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames = {
+ {&getBoolLiteralValue(false), "False"},
+ {&getBoolLiteralValue(true), "True"}};
+ llvm::dbgs() << debugString(Constraints, AtomNames);
+}
+
} // namespace dataflow
} // namespace clang
diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 3aea670f20aa..2b6cd0c4f857 100644
--- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -15,10 +15,8 @@
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
-#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@@ -512,5 +510,9 @@ bool Environment::flowConditionImplies(BoolValue &Val) const {
return DACtx->flowConditionImplies(*FlowConditionToken, Val);
}
+void Environment::dump() const {
+ DACtx->dumpFlowCondition(*FlowConditionToken);
+}
+
} // namespace dataflow
} // namespace clang
diff --git a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
index 305d9d346089..309ff0682f50 100644
--- a/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
+++ b/contrib/llvm-project/clang/lib/Analysis/FlowSensitive/DebugSupport.cpp
@@ -17,6 +17,7 @@
#include "clang/Analysis/FlowSensitive/Solver.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatAdapters.h"
@@ -30,6 +31,28 @@ using llvm::AlignStyle;
using llvm::fmt_pad;
using llvm::formatv;
+std::string debugString(Solver::Result::Assignment Assignment) {
+ switch (Assignment) {
+ case Solver::Result::Assignment::AssignedFalse:
+ return "False";
+ case Solver::Result::Assignment::AssignedTrue:
+ return "True";
+ }
+ llvm_unreachable("Booleans can only be assigned true/false");
+}
+
+std::string debugString(Solver::Result::Status Status) {
+ switch (Status) {
+ case Solver::Result::Status::Satisfiable:
+ return "Satisfiable";
+ case Solver::Result::Status::Unsatisfiable:
+ return "Unsatisfiable";
+ case Solver::Result::Status::TimedOut:
+ return "TimedOut";
+ }
+ llvm_unreachable("Unhandled SAT check result status");
+}
+
namespace {
class DebugStringGenerator {
@@ -80,9 +103,25 @@ public:
return formatv("{0}", fmt_pad(S, Indent, 0));
}
+ std::string debugString(const llvm::DenseSet<BoolValue *> &Constraints) {
+ std::vector<std::string> ConstraintsStrings;
+ ConstraintsStrings.reserve(Constraints.size());
+ for (BoolValue *Constraint : Constraints) {
+ ConstraintsStrings.push_back(debugString(*Constraint));
+ }
+ llvm::sort(ConstraintsStrings);
+
+ std::string Result;
+ for (const std::string &S : ConstraintsStrings) {
+ Result += S;
+ Result += '\n';
+ }
+ return Result;
+ }
+
/// Returns a string representation of a set of boolean `Constraints` and the
/// `Result` of satisfiability checking on the `Constraints`.
- std::string debugString(const std::vector<BoolValue *> &Constraints,
+ std::string debugString(ArrayRef<BoolValue *> &Constraints,
const Solver::Result &Result) {
auto Template = R"(
Constraints
@@ -101,10 +140,9 @@ Constraints
ConstraintsStrings.push_back(debugString(*Constraint));
}
- auto StatusString = debugString(Result.getStatus());
+ auto StatusString = clang::dataflow::debugString(Result.getStatus());
auto Solution = Result.getSolution();
- auto SolutionString =
- Solution.hasValue() ? "\n" + debugString(Solution.value()) : "";
+ auto SolutionString = Solution ? "\n" + debugString(Solution.value()) : "";
return formatv(
Template,
@@ -127,38 +165,14 @@ private:
auto Line = formatv("{0} = {1}",
fmt_align(getAtomName(AtomAssignment.first),
AlignStyle::Left, MaxNameLength),
- debugString(AtomAssignment.second));
+ clang::dataflow::debugString(AtomAssignment.second));
Lines.push_back(Line);
}
- llvm::sort(Lines.begin(), Lines.end());
+ llvm::sort(Lines);
return formatv("{0:$[\n]}", llvm::make_range(Lines.begin(), Lines.end()));
}
- /// Returns a string representation of a boolean assignment to true or false.
- std::string debugString(Solver::Result::Assignment Assignment) {
- switch (Assignment) {
- case Solver::Result::Assignment::AssignedFalse:
- return "False";
- case Solver::Result::Assignment::AssignedTrue:
- return "True";
- }
- llvm_unreachable("Booleans can only be assigned true/false");
- }
-
- /// Returns a string representation of the result status of a SAT check.
- std::string debugString(Solver::Result::Status Status) {
- switch (Status) {
- case Solver::Result::Status::Satisfiable:
- return "Satisfiable";
- case Solver::Result::Status::Unsatisfiable:
- return "Unsatisfiable";
- case Solver::Result::Status::TimedOut:
- return "TimedOut";
- }
- llvm_unreachable("Unhandled SAT check result status");
- }
-
/// Returns the name assigned to `Atom`, either user-specified or created by
/// default rules (B0, B1, ...).
std::string getAtomName(const AtomicBoolValue *Atom) {
@@ -186,8 +200,13 @@ debugString(const BoolValue &B,
}
std::string
-debugString(const std::vector<BoolValue *> &Constraints,
- const Solver::Result &Result,
+debugString(const llvm::DenseSet<BoolValue *> &Constraints,
+ llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames) {
+ return DebugStringGenerator(std::move(AtomNames)).debugString(Constraints);
+}
+
+std::string
+debugString(ArrayRef<BoolValue *> Constraints, const Solver::Result &Result,
llvm::DenseMap<const AtomicBoolValue *, std::string> AtomNames) {
return DebugStringGenerator(std::move(AtomNames))
.debugString(Constraints, Result);
diff --git a/contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp b/contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp
index 03bbf078d7e8..32d950864ce7 100644
--- a/contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp
+++ b/contrib/llvm-project/clang/lib/Analysis/ThreadSafety.cpp
@@ -1679,6 +1679,17 @@ void BuildLockset::checkAccess(const Expr *Exp, AccessKind AK,
return;
}
+ if (const auto *BO = dyn_cast<BinaryOperator>(Exp)) {
+ switch (BO->getOpcode()) {
+ case BO_PtrMemD: // .*
+ return checkAccess(BO->getLHS(), AK, POK);
+ case BO_PtrMemI: // ->*
+ return checkPtAccess(BO->getLHS(), AK, POK);
+ default:
+ return;
+ }
+ }
+
if (const auto *AE = dyn_cast<ArraySubscriptExpr>(Exp)) {
checkPtAccess(AE->getLHS(), AK, POK);
return;
diff --git a/contrib/llvm-project/clang/lib/Basic/MakeSupport.cpp b/contrib/llvm-project/clang/lib/Basic/MakeSupport.cpp
index 37838f7bbc7b..4ddfcc350410 100644
--- a/contrib/llvm-project/clang/lib/Basic/MakeSupport.cpp
+++ b/contrib/llvm-project/clang/lib/Basic/MakeSupport.cpp
@@ -32,4 +32,4 @@ void clang::quoteMakeTarget(StringRef Target, SmallVectorImpl<char> &Res) {
Res.push_back(Target[i]);
}
-} \ No newline at end of file
+}
diff --git a/contrib/llvm-project/clang/lib/Basic/NoSanitizeList.cpp b/contrib/llvm-project/clang/lib/Basic/NoSanitizeList.cpp
index 3efd613b0d33..e7e63c1f419e 100644
--- a/contrib/llvm-project/clang/lib/Basic/NoSanitizeList.cpp
+++ b/contrib/llvm-project/clang/lib/Basic/NoSanitizeList.cpp
@@ -47,6 +47,11 @@ bool NoSanitizeList::containsFile(SanitizerMask Mask, StringRef FileName,
return SSCL->inSection(Mask, "src", FileName, Category);
}
+bool NoSanitizeList::containsMainFile(SanitizerMask Mask, StringRef FileName,
+ StringRef Category) const {
+ return SSCL->inSection(Mask, "mainfile", FileName, Category);
+}
+
bool NoSanitizeList::containsLocation(SanitizerMask Mask, SourceLocation Loc,
StringRef Category) const {
return Loc.isValid() &&
diff --git a/contrib/llvm-project/clang/lib/Basic/Sarif.cpp b/contrib/llvm-project/clang/lib/Basic/Sarif.cpp
new file mode 100644
index 000000000000..faca9c508c08
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Basic/Sarif.cpp
@@ -0,0 +1,389 @@
+//===-- clang/Basic/Sarif.cpp - SarifDocumentWriter class definition ------===//
+//
+// 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 contains the declaration of the SARIFDocumentWriter class, and
+/// associated builders such as:
+/// - \ref SarifArtifact
+/// - \ref SarifArtifactLocation
+/// - \ref SarifRule
+/// - \ref SarifResult
+//===----------------------------------------------------------------------===//
+#include "clang/Basic/Sarif.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/Path.h"
+
+#include <string>
+#include <utility>
+
+using namespace clang;
+using namespace llvm;
+
+using clang::detail::SarifArtifact;
+using clang::detail::SarifArtifactLocation;
+
+static StringRef getFileName(const FileEntry &FE) {
+ StringRef Filename = FE.tryGetRealPathName();
+ if (Filename.empty())
+ Filename = FE.getName();
+ return Filename;
+}
+/// \name URI
+/// @{
+
+/// \internal
+/// \brief
+/// Return the RFC3986 encoding of the input character.
+///
+/// \param C Character to encode to RFC3986.
+///
+/// \return The RFC3986 representation of \c C.
+static std::string percentEncodeURICharacter(char C) {
+ // RFC 3986 claims alpha, numeric, and this handful of
+ // characters are not reserved for the path component and
+ // should be written out directly. Otherwise, percent
+ // encode the character and write that out instead of the
+ // reserved character.
+ if (llvm::isAlnum(C) ||
+ StringRef::npos != StringRef("-._~:@!$&'()*+,;=").find(C))
+ return std::string(&C, 1);
+ return "%" + llvm::toHex(StringRef(&C, 1));
+}
+
+/// \internal
+/// \brief Return a URI representing the given file name.
+///
+/// \param Filename The filename to be represented as URI.
+///
+/// \return RFC3986 URI representing the input file name.
+static std::string fileNameToURI(StringRef Filename) {
+ SmallString<32> Ret = StringRef("file://");
+
+ // Get the root name to see if it has a URI authority.
+ StringRef Root = sys::path::root_name(Filename);
+ if (Root.startswith("//")) {
+ // There is an authority, so add it to the URI.
+ Ret += Root.drop_front(2).str();
+ } else if (!Root.empty()) {
+ // There is no authority, so end the component and add the root to the URI.
+ Ret += Twine("/" + Root).str();
+ }
+
+ auto Iter = sys::path::begin(Filename), End = sys::path::end(Filename);
+ assert(Iter != End && "Expected there to be a non-root path component.");
+ // Add the rest of the path components, encoding any reserved characters;
+ // we skip past the first path component, as it was handled it above.
+ std::for_each(++Iter, End, [&Ret](StringRef Component) {
+ // For reasons unknown to me, we may get a backslash with Windows native
+ // paths for the initial backslash following the drive component, which
+ // we need to ignore as a URI path part.
+ if (Component == "\\")
+ return;
+
+ // Add the separator between the previous path part and the one being
+ // currently processed.
+ Ret += "/";
+
+ // URI encode the part.
+ for (char C : Component) {
+ Ret += percentEncodeURICharacter(C);
+ }
+ });
+
+ return std::string(Ret);
+}
+/// @}
+
+/// \brief Calculate the column position expressed in the number of UTF-8 code
+/// points from column start to the source location
+///
+/// \param Loc The source location whose column needs to be calculated.
+/// \param TokenLen Optional hint for when the token is multiple bytes long.
+///
+/// \return The column number as a UTF-8 aware byte offset from column start to
+/// the effective source location.
+static unsigned int adjustColumnPos(FullSourceLoc Loc,
+ unsigned int TokenLen = 0) {
+ assert(!Loc.isInvalid() && "invalid Loc when adjusting column position");
+
+ std::pair<FileID, unsigned> LocInfo = Loc.getDecomposedLoc();
+ Optional<MemoryBufferRef> Buf =
+ Loc.getManager().getBufferOrNone(LocInfo.first);
+ assert(Buf && "got an invalid buffer for the location's file");
+ assert(Buf->getBufferSize() >= (LocInfo.second + TokenLen) &&
+ "token extends past end of buffer?");
+
+ // Adjust the offset to be the start of the line, since we'll be counting
+ // Unicode characters from there until our column offset.
+ unsigned int Off = LocInfo.second - (Loc.getExpansionColumnNumber() - 1);
+ unsigned int Ret = 1;
+ while (Off < (LocInfo.second + TokenLen)) {
+ Off += getNumBytesForUTF8(Buf->getBuffer()[Off]);
+ Ret++;
+ }
+
+ return Ret;
+}
+
+/// \name SARIF Utilities
+/// @{
+
+/// \internal
+json::Object createMessage(StringRef Text) {
+ return json::Object{{"text", Text.str()}};
+}
+
+/// \internal
+/// \pre CharSourceRange must be a token range
+static json::Object createTextRegion(const SourceManager &SM,
+ const CharSourceRange &R) {
+ FullSourceLoc FirstTokenLoc{R.getBegin(), SM};
+ FullSourceLoc LastTokenLoc{R.getEnd(), SM};
+ json::Object Region{{"startLine", FirstTokenLoc.getExpansionLineNumber()},
+ {"startColumn", adjustColumnPos(FirstTokenLoc)},
+ {"endColumn", adjustColumnPos(LastTokenLoc)}};
+ if (FirstTokenLoc != LastTokenLoc) {
+ Region["endLine"] = LastTokenLoc.getExpansionLineNumber();
+ }
+ return Region;
+}
+
+static json::Object createLocation(json::Object &&PhysicalLocation,
+ StringRef Message = "") {
+ json::Object Ret{{"physicalLocation", std::move(PhysicalLocation)}};
+ if (!Message.empty())
+ Ret.insert({"message", createMessage(Message)});
+ return Ret;
+}
+
+static StringRef importanceToStr(ThreadFlowImportance I) {
+ switch (I) {
+ case ThreadFlowImportance::Important:
+ return "important";
+ case ThreadFlowImportance::Essential:
+ return "essential";
+ case ThreadFlowImportance::Unimportant:
+ return "unimportant";
+ }
+ llvm_unreachable("Fully covered switch is not so fully covered");
+}
+
+static json::Object
+createThreadFlowLocation(json::Object &&Location,
+ const ThreadFlowImportance &Importance) {
+ return json::Object{{"location", std::move(Location)},
+ {"importance", importanceToStr(Importance)}};
+}
+/// @}
+
+json::Object
+SarifDocumentWriter::createPhysicalLocation(const CharSourceRange &R) {
+ assert(R.isValid() &&
+ "Cannot create a physicalLocation from invalid SourceRange!");
+ assert(R.isCharRange() &&
+ "Cannot create a physicalLocation from a token range!");
+ FullSourceLoc Start{R.getBegin(), SourceMgr};
+ const FileEntry *FE = Start.getExpansionLoc().getFileEntry();
+ assert(FE != nullptr && "Diagnostic does not exist within a valid file!");
+
+ const std::string &FileURI = fileNameToURI(getFileName(*FE));
+ auto I = CurrentArtifacts.find(FileURI);
+
+ if (I == CurrentArtifacts.end()) {
+ uint32_t Idx = static_cast<uint32_t>(CurrentArtifacts.size());
+ const SarifArtifactLocation &Location =
+ SarifArtifactLocation::create(FileURI).setIndex(Idx);
+ const SarifArtifact &Artifact = SarifArtifact::create(Location)
+ .setRoles({"resultFile"})
+ .setLength(FE->getSize())
+ .setMimeType("text/plain");
+ auto StatusIter = CurrentArtifacts.insert({FileURI, Artifact});
+ // If inserted, ensure the original iterator points to the newly inserted
+ // element, so it can be used downstream.
+ if (StatusIter.second)
+ I = StatusIter.first;
+ }
+ assert(I != CurrentArtifacts.end() && "Failed to insert new artifact");
+ const SarifArtifactLocation &Location = I->second.Location;
+ uint32_t Idx = Location.Index.value();
+ return json::Object{{{"artifactLocation", json::Object{{{"index", Idx}}}},
+ {"region", createTextRegion(SourceMgr, R)}}};
+}
+
+json::Object &SarifDocumentWriter::getCurrentTool() {
+ assert(!Closed && "SARIF Document is closed. "
+ "Need to call createRun() before using getcurrentTool!");
+
+ // Since Closed = false here, expect there to be at least 1 Run, anything
+ // else is an invalid state.
+ assert(!Runs.empty() && "There are no runs associated with the document!");
+
+ return *Runs.back().getAsObject()->get("tool")->getAsObject();
+}
+
+void SarifDocumentWriter::reset() {
+ CurrentRules.clear();
+ CurrentArtifacts.clear();
+}
+
+void SarifDocumentWriter::endRun() {
+ // Exit early if trying to close a closed Document.
+ if (Closed) {
+ reset();
+ return;
+ }
+
+ // Since Closed = false here, expect there to be at least 1 Run, anything
+ // else is an invalid state.
+ assert(!Runs.empty() && "There are no runs associated with the document!");
+
+ // Flush all the rules.
+ json::Object &Tool = getCurrentTool();
+ json::Array Rules;
+ for (const SarifRule &R : CurrentRules) {
+ json::Object Rule{
+ {"name", R.Name},
+ {"id", R.Id},
+ {"fullDescription", json::Object{{"text", R.Description}}}};
+ if (!R.HelpURI.empty())
+ Rule["helpUri"] = R.HelpURI;
+ Rules.emplace_back(std::move(Rule));
+ }
+ json::Object &Driver = *Tool.getObject("driver");
+ Driver["rules"] = std::move(Rules);
+
+ // Flush all the artifacts.
+ json::Object &Run = getCurrentRun();
+ json::Array *Artifacts = Run.getArray("artifacts");
+ for (const auto &Pair : CurrentArtifacts) {
+ const SarifArtifact &A = Pair.getValue();
+ json::Object Loc{{"uri", A.Location.URI}};
+ if (A.Location.Index.has_value()) {
+ Loc["index"] = static_cast<int64_t>(A.Location.Index.value());
+ }
+ json::Object Artifact;
+ Artifact["location"] = std::move(Loc);
+ if (A.Length.has_value())
+ Artifact["length"] = static_cast<int64_t>(A.Length.value());
+ if (!A.Roles.empty())
+ Artifact["roles"] = json::Array(A.Roles);
+ if (!A.MimeType.empty())
+ Artifact["mimeType"] = A.MimeType;
+ if (A.Offset.has_value())
+ Artifact["offset"] = A.Offset;
+ Artifacts->push_back(json::Value(std::move(Artifact)));
+ }
+
+ // Clear, reset temporaries before next run.
+ reset();
+
+ // Mark the document as closed.
+ Closed = true;
+}
+
+json::Array
+SarifDocumentWriter::createThreadFlows(ArrayRef<ThreadFlow> ThreadFlows) {
+ json::Object Ret{{"locations", json::Array{}}};
+ json::Array Locs;
+ for (const auto &ThreadFlow : ThreadFlows) {
+ json::Object PLoc = createPhysicalLocation(ThreadFlow.Range);
+ json::Object Loc = createLocation(std::move(PLoc), ThreadFlow.Message);
+ Locs.emplace_back(
+ createThreadFlowLocation(std::move(Loc), ThreadFlow.Importance));
+ }
+ Ret["locations"] = std::move(Locs);
+ return json::Array{std::move(Ret)};
+}
+
+json::Object
+SarifDocumentWriter::createCodeFlow(ArrayRef<ThreadFlow> ThreadFlows) {
+ return json::Object{{"threadFlows", createThreadFlows(ThreadFlows)}};
+}
+
+void SarifDocumentWriter::createRun(StringRef ShortToolName,
+ StringRef LongToolName,
+ StringRef ToolVersion) {
+ // Clear resources associated with a previous run.
+ endRun();
+
+ // Signify a new run has begun.
+ Closed = false;
+
+ json::Object Tool{
+ {"driver",
+ json::Object{{"name", ShortToolName},
+ {"fullName", LongToolName},
+ {"language", "en-US"},
+ {"version", ToolVersion},
+ {"informationUri",
+ "https://clang.llvm.org/docs/UsersManual.html"}}}};
+ json::Object TheRun{{"tool", std::move(Tool)},
+ {"results", {}},
+ {"artifacts", {}},
+ {"columnKind", "unicodeCodePoints"}};
+ Runs.emplace_back(std::move(TheRun));
+}
+
+json::Object &SarifDocumentWriter::getCurrentRun() {
+ assert(!Closed &&
+ "SARIF Document is closed. "
+ "Can only getCurrentRun() if document is opened via createRun(), "
+ "create a run first");
+
+ // Since Closed = false here, expect there to be at least 1 Run, anything
+ // else is an invalid state.
+ assert(!Runs.empty() && "There are no runs associated with the document!");
+ return *Runs.back().getAsObject();
+}
+
+size_t SarifDocumentWriter::createRule(const SarifRule &Rule) {
+ size_t Ret = CurrentRules.size();
+ CurrentRules.emplace_back(Rule);
+ return Ret;
+}
+
+void SarifDocumentWriter::appendResult(const SarifResult &Result) {
+ size_t RuleIdx = Result.RuleIdx;
+ assert(RuleIdx < CurrentRules.size() &&
+ "Trying to reference a rule that doesn't exist");
+ json::Object Ret{{"message", createMessage(Result.DiagnosticMessage)},
+ {"ruleIndex", static_cast<int64_t>(RuleIdx)},
+ {"ruleId", CurrentRules[RuleIdx].Id}};
+ if (!Result.Locations.empty()) {
+ json::Array Locs;
+ for (auto &Range : Result.Locations) {
+ Locs.emplace_back(createLocation(createPhysicalLocation(Range)));
+ }
+ Ret["locations"] = std::move(Locs);
+ }
+ if (!Result.ThreadFlows.empty())
+ Ret["codeFlows"] = json::Array{createCodeFlow(Result.ThreadFlows)};
+ json::Object &Run = getCurrentRun();
+ json::Array *Results = Run.getArray("results");
+ Results->emplace_back(std::move(Ret));
+}
+
+json::Object SarifDocumentWriter::createDocument() {
+ // Flush all temporaries to their destinations if needed.
+ endRun();
+
+ json::Object Doc{
+ {"$schema", SchemaURI},
+ {"version", SchemaVersion},
+ };
+ if (!Runs.empty())
+ Doc["runs"] = json::Array(Runs);
+ return Doc;
+}
diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp b/contrib/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp
index 50256d8e210c..80f2601b0a24 100644
--- a/contrib/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/contrib/llvm-project/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -250,6 +250,7 @@ bool AMDGPUTargetInfo::initFeatureMap(
break;
case GK_GFX940:
Features["gfx940-insts"] = true;
+ Features["fp8-insts"] = true;
LLVM_FALLTHROUGH;
case GK_GFX90A:
Features["gfx90a-insts"] = true;
diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp b/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp
index cb2cdb50e18e..7e6c0620385a 100644
--- a/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp
+++ b/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp
@@ -158,8 +158,10 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro(Twine("__riscv_", ExtName), Twine(Version));
}
- if (ISAInfo->hasExtension("m")) {
+ if (ISAInfo->hasExtension("m") || ISAInfo->hasExtension("zmmul"))
Builder.defineMacro("__riscv_mul");
+
+ if (ISAInfo->hasExtension("m")) {
Builder.defineMacro("__riscv_div");
Builder.defineMacro("__riscv_muldiv");
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h b/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h
index 6214148adab9..fe6cc7a2b1c7 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h
+++ b/contrib/llvm-project/clang/lib/CodeGen/ABIInfo.h
@@ -35,10 +35,6 @@ namespace CodeGen {
class CodeGenTypes;
class SwiftABIInfo;
-namespace swiftcall {
- class SwiftAggLowering;
-}
-
// FIXME: All of this stuff should be part of the target interface
// somehow. It is currently here because it is not clear how to factor
// the targets to support this, since the Targets currently live in a
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
index 8c7ee6b078f2..113c629bf9ed 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGBuiltin.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "ABIInfo.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGCall.h b/contrib/llvm-project/clang/lib/CodeGen/CGCall.h
index af63e1bddd2d..59c3f304f59b 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGCall.h
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGCall.h
@@ -22,9 +22,6 @@
#include "clang/AST/Type.h"
#include "llvm/IR/Value.h"
-// FIXME: Restructure so we don't have to expose so much stuff.
-#include "ABIInfo.h"
-
namespace llvm {
class Type;
class Value;
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp
index de5cb913220a..949112c63cc9 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -618,6 +618,130 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() {
CXXThreadLocals.clear();
}
+/* Build the initializer for a C++20 module:
+ This is arranged to be run only once regardless of how many times the module
+ might be included transitively. This arranged by using a control variable.
+
+ First we call any initializers for imported modules.
+ We then call initializers for the Global Module Fragment (if present)
+ We then call initializers for the current module.
+ We then call initializers for the Private Module Fragment (if present)
+*/
+
+void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
+ while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
+ CXXGlobalInits.pop_back();
+
+ // We create the function, even if it is empty, since an importer of this
+ // module will refer to it unconditionally (for the current implementation
+ // there is no way for the importer to know that an importee does not need
+ // an initializer to be run).
+
+ // Module initializers for imported modules are emitted first.
+ // Collect the modules that we import
+ SmallVector<Module *> AllImports;
+ // Ones that we export
+ for (auto I : Primary->Exports)
+ AllImports.push_back(I.getPointer());
+ // Ones that we only import.
+ for (Module *M : Primary->Imports)
+ AllImports.push_back(M);
+
+ SmallVector<llvm::Function *, 8> ModuleInits;
+ for (Module *M : AllImports) {
+ // No Itanium initializer in module map modules.
+ if (M->isModuleMapModule())
+ continue; // TODO: warn of mixed use of module map modules and C++20?
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ SmallString<256> FnName;
+ {
+ llvm::raw_svector_ostream Out(FnName);
+ cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
+ .mangleModuleInitializer(M, Out);
+ }
+ assert(!GetGlobalValue(FnName.str()) &&
+ "We should only have one use of the initializer call");
+ llvm::Function *Fn = llvm::Function::Create(
+ FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
+ ModuleInits.push_back(Fn);
+ }
+ AllImports.clear();
+
+ // Add any initializers with specified priority; this uses the same approach
+ // as EmitCXXGlobalInitFunc().
+ if (!PrioritizedCXXGlobalInits.empty()) {
+ SmallVector<llvm::Function *, 8> LocalCXXGlobalInits;
+ llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
+ PrioritizedCXXGlobalInits.end());
+ for (SmallVectorImpl<GlobalInitData>::iterator
+ I = PrioritizedCXXGlobalInits.begin(),
+ E = PrioritizedCXXGlobalInits.end();
+ I != E;) {
+ SmallVectorImpl<GlobalInitData>::iterator PrioE =
+ std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp());
+
+ for (; I < PrioE; ++I)
+ ModuleInits.push_back(I->second);
+ }
+ PrioritizedCXXGlobalInits.clear();
+ }
+
+ // Now append the ones without specified priority.
+ for (auto F : CXXGlobalInits)
+ ModuleInits.push_back(F);
+ CXXGlobalInits.clear();
+
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ const CGFunctionInfo &FI = getTypes().arrangeNullaryFunction();
+
+ // We now build the initializer for this module, which has a mangled name
+ // as per the Itanium ABI . The action of the initializer is guarded so that
+ // each init is run just once (even though a module might be imported
+ // multiple times via nested use).
+ llvm::Function *Fn;
+ llvm::GlobalVariable *Guard = nullptr;
+ {
+ SmallString<256> InitFnName;
+ llvm::raw_svector_ostream Out(InitFnName);
+ cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
+ .mangleModuleInitializer(Primary, Out);
+ Fn = CreateGlobalInitOrCleanUpFunction(
+ FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
+ llvm::GlobalVariable::ExternalLinkage);
+
+ Guard = new llvm::GlobalVariable(getModule(), Int8Ty, /*isConstant=*/false,
+ llvm::GlobalVariable::InternalLinkage,
+ llvm::ConstantInt::get(Int8Ty, 0),
+ InitFnName.str() + "__in_chrg");
+ }
+ CharUnits GuardAlign = CharUnits::One();
+ Guard->setAlignment(GuardAlign.getAsAlign());
+
+ CodeGenFunction(*this).GenerateCXXGlobalInitFunc(
+ Fn, ModuleInits, ConstantAddress(Guard, Int8Ty, GuardAlign));
+ // We allow for the case that a module object is added to a linked binary
+ // without a specific call to the the initializer. This also ensure that
+ // implementation partition initializers are called when the partition
+ // is not imported as an interface.
+ AddGlobalCtor(Fn);
+
+ // See the comment in EmitCXXGlobalInitFunc about OpenCL global init
+ // functions.
+ if (getLangOpts().OpenCL) {
+ GenKernelArgMetadata(Fn);
+ Fn->setCallingConv(llvm::CallingConv::SPIR_KERNEL);
+ }
+
+ assert(!getLangOpts().CUDA || !getLangOpts().CUDAIsDevice ||
+ getLangOpts().GPUAllowDeviceInit);
+ if (getLangOpts().HIP && getLangOpts().CUDAIsDevice) {
+ Fn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL);
+ Fn->addFnAttr("device-init");
+ }
+
+ ModuleInits.clear();
+}
+
static SmallString<128> getTransformedFileName(llvm::Module &M) {
SmallString<128> FileName = llvm::sys::path::filename(M.getName());
@@ -650,7 +774,29 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
CXXGlobalInits.pop_back();
- if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
+ // When we import C++20 modules, we must run their initializers first.
+ SmallVector<llvm::Function *, 8> ModuleInits;
+ if (CXX20ModuleInits)
+ for (Module *M : ImportedModules) {
+ // No Itanium initializer in module map modules.
+ if (M->isModuleMapModule())
+ continue;
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ SmallString<256> FnName;
+ {
+ llvm::raw_svector_ostream Out(FnName);
+ cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
+ .mangleModuleInitializer(M, Out);
+ }
+ assert(!GetGlobalValue(FnName.str()) &&
+ "We should only have one use of the initializer call");
+ llvm::Function *Fn = llvm::Function::Create(
+ FTy, llvm::Function::ExternalLinkage, FnName.str(), &getModule());
+ ModuleInits.push_back(Fn);
+ }
+
+ if (ModuleInits.empty() && CXXGlobalInits.empty() &&
+ PrioritizedCXXGlobalInits.empty())
return;
llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
@@ -676,6 +822,13 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
FTy, "_GLOBAL__I_" + getPrioritySuffix(Priority), FI);
+ // Prepend the module inits to the highest priority set.
+ if (!ModuleInits.empty()) {
+ for (auto F : ModuleInits)
+ LocalCXXGlobalInits.push_back(F);
+ ModuleInits.clear();
+ }
+
for (; I < PrioE; ++I)
LocalCXXGlobalInits.push_back(I->second);
@@ -685,17 +838,33 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
PrioritizedCXXGlobalInits.clear();
}
- if (getCXXABI().useSinitAndSterm() && CXXGlobalInits.empty())
+ if (getCXXABI().useSinitAndSterm() && ModuleInits.empty() &&
+ CXXGlobalInits.empty())
return;
+ for (auto F : CXXGlobalInits)
+ ModuleInits.push_back(F);
+ CXXGlobalInits.clear();
+
// Include the filename in the symbol name. Including "sub_" matches gcc
// and makes sure these symbols appear lexicographically behind the symbols
// with priority emitted above.
- llvm::Function *Fn = CreateGlobalInitOrCleanUpFunction(
- FTy, llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
- FI);
-
- CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, CXXGlobalInits);
+ llvm::Function *Fn;
+ if (CXX20ModuleInits && getContext().getModuleForCodeGen()) {
+ SmallString<256> InitFnName;
+ llvm::raw_svector_ostream Out(InitFnName);
+ cast<ItaniumMangleContext>(getCXXABI().getMangleContext())
+ .mangleModuleInitializer(getContext().getModuleForCodeGen(), Out);
+ Fn = CreateGlobalInitOrCleanUpFunction(
+ FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
+ llvm::GlobalVariable::ExternalLinkage);
+ } else
+ Fn = CreateGlobalInitOrCleanUpFunction(
+ FTy,
+ llvm::Twine("_GLOBAL__sub_I_", getTransformedFileName(getModule())),
+ FI);
+
+ CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, ModuleInits);
AddGlobalCtor(Fn);
// In OpenCL global init functions must be converted to kernels in order to
@@ -718,7 +887,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
Fn->addFnAttr("device-init");
}
- CXXGlobalInits.clear();
+ ModuleInits.clear();
}
void CodeGenModule::EmitCXXGlobalCleanUpFunc() {
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp
index cbeb6c938bee..bf3dd812b9e8 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGExpr.cpp
@@ -877,7 +877,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
/// Determine whether this expression refers to a flexible array member in a
/// struct. We disable array bounds checks for such members.
-static bool isFlexibleArrayMemberExpr(const Expr *E) {
+static bool isFlexibleArrayMemberExpr(const Expr *E,
+ unsigned StrictFlexArraysLevel) {
// For compatibility with existing code, we treat arrays of length 0 or
// 1 as flexible array members.
// FIXME: This is inconsistent with the warning code in SemaChecking. Unify
@@ -886,6 +887,11 @@ static bool isFlexibleArrayMemberExpr(const Expr *E) {
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
// FIXME: Sema doesn't treat [1] as a flexible array member if the bound
// was produced by macro expansion.
+ if (StrictFlexArraysLevel >= 2 && CAT->getSize().ugt(0))
+ return false;
+ // FIXME: While the default -fstrict-flex-arrays=0 permits Size>1 trailing
+ // arrays to be treated as flexible-array-members, we still emit ubsan
+ // checks as if they are not.
if (CAT->getSize().ugt(1))
return false;
} else if (!isa<IncompleteArrayType>(AT))
@@ -900,8 +906,10 @@ static bool isFlexibleArrayMemberExpr(const Expr *E) {
if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
// FIXME: Sema doesn't treat a T[1] union member as a flexible array
// member, only a T[0] or T[] member gets that treatment.
+ // Under StrictFlexArraysLevel, obey c99+ that disallows FAM in union, see
+ // C11 6.7.2.1 §18
if (FD->getParent()->isUnion())
- return true;
+ return StrictFlexArraysLevel < 2;
RecordDecl::field_iterator FI(
DeclContext::decl_iterator(const_cast<FieldDecl *>(FD)));
return ++FI == FD->getParent()->field_end();
@@ -954,8 +962,10 @@ llvm::Value *CodeGenFunction::LoadPassedObjectSize(const Expr *E,
/// If Base is known to point to the start of an array, return the length of
/// that array. Return 0 if the length cannot be determined.
-static llvm::Value *getArrayIndexingBound(
- CodeGenFunction &CGF, const Expr *Base, QualType &IndexedType) {
+static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
+ const Expr *Base,
+ QualType &IndexedType,
+ unsigned StrictFlexArraysLevel) {
// For the vector indexing extension, the bound is the number of elements.
if (const VectorType *VT = Base->getType()->getAs<VectorType>()) {
IndexedType = Base->getType();
@@ -966,7 +976,7 @@ static llvm::Value *getArrayIndexingBound(
if (const auto *CE = dyn_cast<CastExpr>(Base)) {
if (CE->getCastKind() == CK_ArrayToPointerDecay &&
- !isFlexibleArrayMemberExpr(CE->getSubExpr())) {
+ !isFlexibleArrayMemberExpr(CE->getSubExpr(), StrictFlexArraysLevel)) {
IndexedType = CE->getSubExpr()->getType();
const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe();
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
@@ -993,8 +1003,11 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
"should not be called unless adding bounds checks");
SanitizerScope SanScope(this);
+ const unsigned StrictFlexArraysLevel = getLangOpts().StrictFlexArrays;
+
QualType IndexedType;
- llvm::Value *Bound = getArrayIndexingBound(*this, Base, IndexedType);
+ llvm::Value *Bound =
+ getArrayIndexingBound(*this, Base, IndexedType, StrictFlexArraysLevel);
if (!Bound)
return;
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGObjCRuntime.h b/contrib/llvm-project/clang/lib/CodeGen/CGObjCRuntime.h
index bb27c38db204..3bd981256f47 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGObjCRuntime.h
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGObjCRuntime.h
@@ -34,7 +34,8 @@ namespace llvm {
namespace clang {
namespace CodeGen {
- class CodeGenFunction;
+class CGFunctionInfo;
+class CodeGenFunction;
}
class FieldDecl;
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp
index df7e5608f8f0..05ab16668743 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp
@@ -2603,14 +2603,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
for (const auto *E : GS->labels()) {
JumpDest Dest = getJumpDestForLabel(E->getLabel());
Transfer.push_back(Dest.getBlock());
- llvm::BlockAddress *BA =
- llvm::BlockAddress::get(CurFn, Dest.getBlock());
- Args.push_back(BA);
- ArgTypes.push_back(BA->getType());
- ArgElemTypes.push_back(nullptr);
if (!Constraints.empty())
Constraints += ',';
- Constraints += 'i';
+ Constraints += "!i";
}
Fallthrough = createBasicBlock("asm.fallthrough");
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp
index db0b2ffd3a4f..aa55cdaca5dc 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -5203,8 +5203,30 @@ void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
}
+bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T) {
+ return T.clauses().empty();
+}
+
void CodeGenFunction::EmitOMPTaskgroupDirective(
const OMPTaskgroupDirective &S) {
+ OMPLexicalScope Scope(*this, S, OMPD_unknown);
+ if (CGM.getLangOpts().OpenMPIRBuilder && isSupportedByOpenMPIRBuilder(S)) {
+ llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder();
+ using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
+ InsertPointTy AllocaIP(AllocaInsertPt->getParent(),
+ AllocaInsertPt->getIterator());
+
+ auto BodyGenCB = [&, this](InsertPointTy AllocaIP,
+ InsertPointTy CodeGenIP) {
+ Builder.restoreIP(CodeGenIP);
+ EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
+ };
+ CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
+ if (!CapturedStmtInfo)
+ CapturedStmtInfo = &CapStmtInfo;
+ Builder.restoreIP(OMPBuilder.createTaskgroup(Builder, AllocaIP, BodyGenCB));
+ return;
+ }
auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Action.Enter(CGF);
if (const Expr *E = S.getReductionRef()) {
@@ -5230,7 +5252,6 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
}
CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
};
- OMPLexicalScope Scope(*this, S, OMPD_unknown);
CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp
index 17c1c91c7e8f..5012bd822bd3 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -852,7 +852,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}
if (CGM.getCodeGenOpts().getProfileInstr() != CodeGenOptions::ProfileNone)
- if (CGM.isProfileInstrExcluded(Fn, Loc))
+ if (CGM.isFunctionBlockedFromProfileInstr(Fn, Loc))
Fn->addFnAttr(llvm::Attribute::NoProfile);
unsigned Count, Offset;
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
index c372bab1eccb..101080b6fe13 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
+#include "ABIInfo.h"
#include "CGBlocks.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
@@ -32,7 +33,6 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Mangle.h"
-#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
@@ -58,6 +58,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/ProfileSummary.h"
#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/Support/CRC.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
@@ -136,6 +137,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
GlobalsInt8PtrTy = Int8Ty->getPointerTo(DL.getDefaultGlobalsAddressSpace());
ASTAllocaAddressSpace = getTargetCodeGenInfo().getASTAllocaAddressSpace();
+ // Build C++20 Module initializers.
+ // TODO: Add Microsoft here once we know the mangling required for the
+ // initializers.
+ CXX20ModuleInits =
+ LangOpts.CPlusPlusModules && getCXXABI().getMangleContext().getKind() ==
+ ItaniumMangleContext::MK_Itanium;
+
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
if (LangOpts.ObjC)
@@ -510,6 +518,9 @@ static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO,
}
void CodeGenModule::Release() {
+ Module *Primary = getContext().getModuleForCodeGen();
+ if (CXX20ModuleInits && Primary && !Primary->isModuleMapModule())
+ EmitModuleInitializers(Primary);
EmitDeferred();
DeferredDecls.insert(EmittedDeferredDecls.begin(),
EmittedDeferredDecls.end());
@@ -518,7 +529,10 @@ void CodeGenModule::Release() {
applyGlobalValReplacements();
applyReplacements();
emitMultiVersionFunctions();
- EmitCXXGlobalInitFunc();
+ if (CXX20ModuleInits && Primary && Primary->isInterfaceOrPartition())
+ EmitCXXModuleInitFunc(Primary);
+ else
+ EmitCXXGlobalInitFunc();
EmitCXXGlobalCleanUpFunc();
registerGlobalDtorsWithAtExit();
EmitCXXThreadLocalInitFunc();
@@ -742,19 +756,22 @@ void CodeGenModule::Release() {
if (CodeGenOpts.CFProtectionReturn &&
Target.checkCFProtectionReturnSupported(getDiags())) {
// Indicate that we want to instrument return control flow protection.
- getModule().addModuleFlag(llvm::Module::Override, "cf-protection-return",
+ getModule().addModuleFlag(llvm::Module::Min, "cf-protection-return",
1);
}
if (CodeGenOpts.CFProtectionBranch &&
Target.checkCFProtectionBranchSupported(getDiags())) {
// Indicate that we want to instrument branch control flow protection.
- getModule().addModuleFlag(llvm::Module::Override, "cf-protection-branch",
+ getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch",
1);
}
if (CodeGenOpts.IBTSeal)
- getModule().addModuleFlag(llvm::Module::Override, "ibt-seal", 1);
+ getModule().addModuleFlag(llvm::Module::Min, "ibt-seal", 1);
+
+ if (CodeGenOpts.FunctionReturnThunks)
+ getModule().addModuleFlag(llvm::Module::Override, "function_return_thunk_extern", 1);
// Add module metadata for return address signing (ignoring
// non-leaf/all) and stack tagging. These are actually turned on by function
@@ -2498,6 +2515,31 @@ static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
}
}
+void CodeGenModule::EmitModuleInitializers(clang::Module *Primary) {
+ // Emit the initializers in the order that sub-modules appear in the
+ // source, first Global Module Fragments, if present.
+ if (auto GMF = Primary->getGlobalModuleFragment()) {
+ for (Decl *D : getContext().getModuleInitializers(GMF)) {
+ assert(D->getKind() == Decl::Var && "GMF initializer decl is not a var?");
+ EmitTopLevelDecl(D);
+ }
+ }
+ // Second any associated with the module, itself.
+ for (Decl *D : getContext().getModuleInitializers(Primary)) {
+ // Skip import decls, the inits for those are called explicitly.
+ if (D->getKind() == Decl::Import)
+ continue;
+ EmitTopLevelDecl(D);
+ }
+ // Third any associated with the Privat eMOdule Fragment, if present.
+ if (auto PMF = Primary->getPrivateModuleFragment()) {
+ for (Decl *D : getContext().getModuleInitializers(PMF)) {
+ assert(D->getKind() == Decl::Var && "PMF initializer decl is not a var?");
+ EmitTopLevelDecl(D);
+ }
+ }
+}
+
void CodeGenModule::EmitModuleLinkOptions() {
// Collect the set of all of the modules we want to visit to emit link
// options, which is essentially the imported modules and all of their
@@ -2776,16 +2818,18 @@ bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind, llvm::Function *Fn,
// NoSanitize by function name.
if (NoSanitizeL.containsFunction(Kind, Fn->getName()))
return true;
- // NoSanitize by location.
+ // NoSanitize by location. Check "mainfile" prefix.
+ auto &SM = Context.getSourceManager();
+ const FileEntry &MainFile = *SM.getFileEntryForID(SM.getMainFileID());
+ if (NoSanitizeL.containsMainFile(Kind, MainFile.getName()))
+ return true;
+
+ // Check "src" prefix.
if (Loc.isValid())
return NoSanitizeL.containsLocation(Kind, Loc);
// If location is unknown, this may be a compiler-generated function. Assume
// it's located in the main file.
- auto &SM = Context.getSourceManager();
- if (const auto *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- return NoSanitizeL.containsFile(Kind, MainFile->getName());
- }
- return false;
+ return NoSanitizeL.containsFile(Kind, MainFile.getName());
}
bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind,
@@ -2795,8 +2839,13 @@ bool CodeGenModule::isInNoSanitizeList(SanitizerMask Kind,
const auto &NoSanitizeL = getContext().getNoSanitizeList();
if (NoSanitizeL.containsGlobal(Kind, GV->getName(), Category))
return true;
+ auto &SM = Context.getSourceManager();
+ if (NoSanitizeL.containsMainFile(
+ Kind, SM.getFileEntryForID(SM.getMainFileID())->getName(), Category))
+ return true;
if (NoSanitizeL.containsLocation(Kind, Loc, Category))
return true;
+
// Check global type.
if (!Ty.isNull()) {
// Drill down the array types: if global variable of a fixed type is
@@ -2840,8 +2889,8 @@ bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
return true;
}
-bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn,
- SourceLocation Loc) const {
+bool CodeGenModule::isFunctionBlockedByProfileList(llvm::Function *Fn,
+ SourceLocation Loc) const {
const auto &ProfileList = getContext().getProfileList();
// If the profile list is empty, then instrument everything.
if (ProfileList.isEmpty())
@@ -2868,6 +2917,20 @@ bool CodeGenModule::isProfileInstrExcluded(llvm::Function *Fn,
return ProfileList.getDefault();
}
+bool CodeGenModule::isFunctionBlockedFromProfileInstr(
+ llvm::Function *Fn, SourceLocation Loc) const {
+ if (isFunctionBlockedByProfileList(Fn, Loc))
+ return true;
+
+ auto NumGroups = getCodeGenOpts().ProfileTotalFunctionGroups;
+ if (NumGroups > 1) {
+ auto Group = llvm::crc32(arrayRefFromStringRef(Fn->getName())) % NumGroups;
+ if (Group != getCodeGenOpts().ProfileSelectedFunctionGroup)
+ return true;
+ }
+ return false;
+}
+
bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {
// Never defer when EmitAllDecls is specified.
if (LangOpts.EmitAllDecls)
@@ -2903,12 +2966,20 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) {
// explicitly instantiated, so they should not be emitted eagerly.
return false;
}
- if (const auto *VD = dyn_cast<VarDecl>(Global))
+ if (const auto *VD = dyn_cast<VarDecl>(Global)) {
if (Context.getInlineVariableDefinitionKind(VD) ==
ASTContext::InlineVariableDefinitionKind::WeakUnknown)
// A definition of an inline constexpr static data member may change
// linkage later if it's redeclared outside the class.
return false;
+ if (CXX20ModuleInits && VD->getOwningModule() &&
+ !VD->getOwningModule()->isModuleMapModule()) {
+ // For CXX20, module-owned initializers need to be deferred, since it is
+ // not known at this point if they will be run for the current module or
+ // as part of the initializer for an imported one.
+ return false;
+ }
+ }
// If OpenMP is enabled and threadprivates must be generated like TLS, delay
// codegen for global variables, because they may be marked as threadprivate.
if (LangOpts.OpenMP && LangOpts.OpenMPUseTLS &&
@@ -6208,6 +6279,16 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
DI->EmitImportDecl(*Import);
}
+ // For C++ standard modules we are done - we will call the module
+ // initializer for imported modules, and that will likewise call those for
+ // any imports it has.
+ if (CXX20ModuleInits && Import->getImportedOwningModule() &&
+ !Import->getImportedOwningModule()->isModuleMapModule())
+ break;
+
+ // For clang C++ module map modules the initializers for sub-modules are
+ // emitted here.
+
// Find all of the submodules and emit the module initializers.
llvm::SmallPtrSet<clang::Module *, 16> Visited;
SmallVector<clang::Module *, 16> Stack;
@@ -6892,3 +6973,31 @@ void CodeGenModule::printPostfixForExternalizedDecl(llvm::raw_ostream &OS,
OS << getContext().getCUIDHash();
}
}
+
+void CodeGenModule::moveLazyEmissionStates(CodeGenModule *NewBuilder) {
+ assert(DeferredDeclsToEmit.empty() &&
+ "Should have emitted all decls deferred to emit.");
+ assert(NewBuilder->DeferredDecls.empty() &&
+ "Newly created module should not have deferred decls");
+ NewBuilder->DeferredDecls = std::move(DeferredDecls);
+
+ assert(NewBuilder->DeferredVTables.empty() &&
+ "Newly created module should not have deferred vtables");
+ NewBuilder->DeferredVTables = std::move(DeferredVTables);
+
+ assert(NewBuilder->MangledDeclNames.empty() &&
+ "Newly created module should not have mangled decl names");
+ assert(NewBuilder->Manglings.empty() &&
+ "Newly created module should not have manglings");
+ NewBuilder->Manglings = std::move(Manglings);
+
+ assert(WeakRefReferences.empty() && "Not all WeakRefRefs have been applied");
+ NewBuilder->WeakRefReferences = std::move(WeakRefReferences);
+
+ NewBuilder->TBAA = std::move(TBAA);
+
+ assert(NewBuilder->EmittedDeferredDecls.empty() &&
+ "Still have (unmerged) EmittedDeferredDecls deferred decls");
+
+ NewBuilder->EmittedDeferredDecls = std::move(EmittedDeferredDecls);
+}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h
index 10b49da27dab..c939e7a309f5 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h
+++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenModule.h
@@ -303,7 +303,7 @@ private:
std::unique_ptr<CGCXXABI> ABI;
llvm::LLVMContext &VMContext;
std::string ModuleNameHash;
-
+ bool CXX20ModuleInits = false;
std::unique_ptr<CodeGenTBAA> TBAA;
mutable std::unique_ptr<TargetCodeGenInfo> TheTargetCodeGenInfo;
@@ -1340,9 +1340,15 @@ public:
bool imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc,
StringRef Category = StringRef()) const;
- /// Returns true if function at the given location should be excluded from
- /// profile instrumentation.
- bool isProfileInstrExcluded(llvm::Function *Fn, SourceLocation Loc) const;
+ /// \returns true if \p Fn at \p Loc should be excluded from profile
+ /// instrumentation by the SCL passed by \p -fprofile-list.
+ bool isFunctionBlockedByProfileList(llvm::Function *Fn,
+ SourceLocation Loc) const;
+
+ /// \returns true if \p Fn at \p Loc should be excluded from profile
+ /// instrumentation.
+ bool isFunctionBlockedFromProfileInstr(llvm::Function *Fn,
+ SourceLocation Loc) const;
SanitizerMetadata *getSanitizerMetadata() {
return SanitizerMD.get();
@@ -1508,34 +1514,7 @@ public:
/// Move some lazily-emitted states to the NewBuilder. This is especially
/// essential for the incremental parsing environment like Clang Interpreter,
/// because we'll lose all important information after each repl.
- void moveLazyEmissionStates(CodeGenModule *NewBuilder) {
- assert(DeferredDeclsToEmit.empty() &&
- "Should have emitted all decls deferred to emit.");
- assert(NewBuilder->DeferredDecls.empty() &&
- "Newly created module should not have deferred decls");
- NewBuilder->DeferredDecls = std::move(DeferredDecls);
-
- assert(NewBuilder->DeferredVTables.empty() &&
- "Newly created module should not have deferred vtables");
- NewBuilder->DeferredVTables = std::move(DeferredVTables);
-
- assert(NewBuilder->MangledDeclNames.empty() &&
- "Newly created module should not have mangled decl names");
- assert(NewBuilder->Manglings.empty() &&
- "Newly created module should not have manglings");
- NewBuilder->Manglings = std::move(Manglings);
-
- assert(WeakRefReferences.empty() &&
- "Not all WeakRefRefs have been applied");
- NewBuilder->WeakRefReferences = std::move(WeakRefReferences);
-
- NewBuilder->TBAA = std::move(TBAA);
-
- assert(NewBuilder->EmittedDeferredDecls.empty() &&
- "Still have (unmerged) EmittedDeferredDecls deferred decls");
-
- NewBuilder->EmittedDeferredDecls = std::move(EmittedDeferredDecls);
- }
+ void moveLazyEmissionStates(CodeGenModule *NewBuilder);
private:
llvm::Constant *GetOrCreateLLVMFunction(
@@ -1593,6 +1572,9 @@ private:
/// Emit the function that initializes C++ thread_local variables.
void EmitCXXThreadLocalInitFunc();
+ /// Emit the function that initializes global variables for a C++ Module.
+ void EmitCXXModuleInitFunc(clang::Module *Primary);
+
/// Emit the function that initializes C++ globals.
void EmitCXXGlobalInitFunc();
@@ -1660,6 +1642,9 @@ private:
/// Emit the llvm.used and llvm.compiler.used metadata.
void emitLLVMUsed();
+ /// For C++20 Itanium ABI, emit the initializers for the module.
+ void EmitModuleInitializers(clang::Module *Primary);
+
/// Emit the link options introduced by imported modules.
void EmitModuleLinkOptions();
diff --git a/contrib/llvm-project/clang/lib/CodeGen/SwiftCallingConv.cpp b/contrib/llvm-project/clang/lib/CodeGen/SwiftCallingConv.cpp
index 1d712f4fde3c..8fb24fcecf53 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/SwiftCallingConv.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/SwiftCallingConv.cpp
@@ -11,9 +11,10 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGen/SwiftCallingConv.h"
-#include "clang/Basic/TargetInfo.h"
+#include "ABIInfo.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
+#include "clang/Basic/TargetInfo.h"
using namespace clang;
using namespace CodeGen;
diff --git a/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp
index 8eaed1db8e7d..d1ee61eab9d6 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.cpp
@@ -35,7 +35,7 @@
#include "llvm/IR/Type.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm> // std::sort
+#include <algorithm>
using namespace clang;
using namespace CodeGen;
@@ -443,6 +443,9 @@ static Address emitMergePHI(CodeGenFunction &CGF,
return Address(PHI, Addr1.getElementType(), Align);
}
+TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info)
+ : Info(std::move(Info)) {}
+
TargetCodeGenInfo::~TargetCodeGenInfo() = default;
// If someone can figure out a general rule for this, that would be great.
@@ -10446,6 +10449,15 @@ ABIArgInfo SPIRVABIInfo::classifyKernelArgumentType(QualType Ty) const {
LTy = llvm::PointerType::getWithSamePointeeType(PtrTy, GlobalAS);
return ABIArgInfo::getDirect(LTy, 0, nullptr, false);
}
+
+ // Force copying aggregate type in kernel arguments by value when
+ // compiling CUDA targeting SPIR-V. This is required for the object
+ // copied to be valid on the device.
+ // This behavior follows the CUDA spec
+ // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-function-argument-processing,
+ // and matches the NVPTX implementation.
+ if (isAggregateTypeForABI(Ty))
+ return getNaturalAlignIndirect(Ty, /* byval */ true);
}
return classifyArgumentType(Ty);
}
diff --git a/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h b/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h
index bdd64977b475..30421612015b 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h
+++ b/contrib/llvm-project/clang/lib/CodeGen/TargetInfo.h
@@ -43,10 +43,10 @@ class CGBlockInfo;
/// codegeneration issues, like target-specific attributes, builtins and so
/// on.
class TargetCodeGenInfo {
- std::unique_ptr<ABIInfo> Info = nullptr;
+ std::unique_ptr<ABIInfo> Info;
public:
- TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info) : Info(std::move(Info)) {}
+ TargetCodeGenInfo(std::unique_ptr<ABIInfo> Info);
virtual ~TargetCodeGenInfo();
/// getABIInfo() - Returns ABI info helper for the target.
diff --git a/contrib/llvm-project/clang/lib/Driver/Driver.cpp b/contrib/llvm-project/clang/lib/Driver/Driver.cpp
index 3a8400a55741..3f29afd35971 100644
--- a/contrib/llvm-project/clang/lib/Driver/Driver.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/Driver.cpp
@@ -4432,6 +4432,11 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
types::ID InputType = Input.first;
const Arg *InputArg = Input.second;
+ // The toolchain can be active for unsupported file types.
+ if ((Kind == Action::OFK_Cuda && !types::isCuda(InputType)) ||
+ (Kind == Action::OFK_HIP && !types::isHIP(InputType)))
+ continue;
+
// Get the product of all bound architectures and toolchains.
SmallVector<std::pair<const ToolChain *, StringRef>> TCAndArchs;
for (const ToolChain *TC : ToolChains)
@@ -4473,6 +4478,15 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
}
}
+ // Compiling HIP in non-RDC mode requires linking each action individually.
+ for (Action *&A : DeviceActions) {
+ if (A->getType() != types::TY_Object || Kind != Action::OFK_HIP ||
+ Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
+ continue;
+ ActionList LinkerInput = {A};
+ A = C.MakeAction<LinkJobAction>(LinkerInput, types::TY_Image);
+ }
+
auto TCAndArch = TCAndArchs.begin();
for (Action *A : DeviceActions) {
DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
@@ -4486,15 +4500,27 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
if (offloadDeviceOnly())
return C.MakeAction<OffloadAction>(DDeps, types::TY_Nothing);
+ if (OffloadActions.empty())
+ return HostAction;
+
OffloadAction::DeviceDependences DDep;
if (C.isOffloadingHostKind(Action::OFK_Cuda) &&
!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) {
- // If we are not in RDC-mode we just emit the final CUDA fatbinary for each
- // translation unit without requiring any linking.
+ // If we are not in RDC-mode we just emit the final CUDA fatbinary for
+ // each translation unit without requiring any linking.
Action *FatbinAction =
C.MakeAction<LinkJobAction>(OffloadActions, types::TY_CUDA_FATBIN);
DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_Cuda>(),
nullptr, Action::OFK_Cuda);
+ } else if (C.isOffloadingHostKind(Action::OFK_HIP) &&
+ !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
+ false)) {
+ // If we are not in RDC-mode we just emit the final HIP fatbinary for each
+ // translation unit, linking each input individually.
+ Action *FatbinAction =
+ C.MakeAction<LinkJobAction>(OffloadActions, types::TY_HIP_FATBIN);
+ DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_HIP>(),
+ nullptr, Action::OFK_HIP);
} else {
// Package all the offloading actions into a single output that can be
// embedded in the host and linked.
@@ -4503,6 +4529,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
DDep.add(*PackagerAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
nullptr, Action::OFK_None);
}
+
OffloadAction::HostDependence HDep(
*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
/*BoundArch=*/nullptr, isa<CompileJobAction>(HostAction) ? DDep : DDeps);
@@ -6254,6 +6281,7 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
if (IsClCompatMode) {
// Include CL and Core options.
IncludedFlagsBitmask |= options::CLOption;
+ IncludedFlagsBitmask |= options::CLDXCOption;
IncludedFlagsBitmask |= options::CoreOption;
} else {
ExcludedFlagsBitmask |= options::CLOption;
@@ -6261,10 +6289,14 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
if (IsDXCMode()) {
// Include DXC and Core options.
IncludedFlagsBitmask |= options::DXCOption;
+ IncludedFlagsBitmask |= options::CLDXCOption;
IncludedFlagsBitmask |= options::CoreOption;
} else {
ExcludedFlagsBitmask |= options::DXCOption;
}
+ if (!IsClCompatMode && !IsDXCMode())
+ ExcludedFlagsBitmask |= options::CLDXCOption;
+
return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
}
diff --git a/contrib/llvm-project/clang/lib/Driver/Multilib.cpp b/contrib/llvm-project/clang/lib/Driver/Multilib.cpp
index ab44ba50b5d5..ec619874ad60 100644
--- a/contrib/llvm-project/clang/lib/Driver/Multilib.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/Multilib.cpp
@@ -267,10 +267,9 @@ bool MultilibSet::select(const Multilib::flags_list &Flags, Multilib &M) const {
}
// Sort multilibs by priority and select the one with the highest priority.
- llvm::sort(Filtered.begin(), Filtered.end(),
- [](const Multilib &a, const Multilib &b) -> bool {
- return a.priority() > b.priority();
- });
+ llvm::sort(Filtered, [](const Multilib &a, const Multilib &b) -> bool {
+ return a.priority() > b.priority();
+ });
if (Filtered[0].priority() > Filtered[1].priority()) {
M = Filtered[0];
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
index 5130eb9b72c1..7a4319ea680f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
@@ -1013,6 +1013,8 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
index 878b84a77702..64be5fe23558 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/AIX.cpp
@@ -222,11 +222,13 @@ void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
const Driver &D = getDriver();
- // Add the Clang builtin headers (<resource>/include).
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
- path::append(P, "/include");
- addSystemInclude(DriverArgs, CC1Args, P.str());
+ // Add the PowerPC intrinsic headers (<resource>/include/ppc_wrappers)
+ path::append(P, "include", "ppc_wrappers");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ // Add the Clang builtin headers (<resource>/include)
+ addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str()));
}
// Return if -nostdlibinc is specified as a driver option.
@@ -275,6 +277,8 @@ void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::report_fatal_error("linking libstdc++ unimplemented on AIX");
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
return;
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp
index 40f9e56b38e9..a9c13464a0d6 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Ananas.cpp
@@ -71,7 +71,7 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
- } else {
+ } else if (!Args.hasArg(options::OPT_r)) {
Args.AddAllArgs(CmdArgs, options::OPT_pie);
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/lib/ld-ananas.so");
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index ca625c822d05..f9f1c7835a7a 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "RISCV.h"
+#include "../Clang.h"
#include "ToolChains/CommonArgs.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Driver/Driver.h"
@@ -138,10 +139,17 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// FreeBSD local, because ld.lld doesn't support relaxations
// -mno-relax is default, unless -mrelax is specified.
- if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false))
+ if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, false)) {
Features.push_back("+relax");
- else
+ // -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing
+ // into .debug_addr, which is currently not implemented.
+ Arg *A;
+ if (getDebugFissionKind(D, Args, A) != DwarfFissionKind::None)
+ D.Diag(clang::diag::err_drv_riscv_unsupported_with_linker_relaxation)
+ << A->getAsString(Args);
+ } else {
Features.push_back("-relax");
+ }
// GCC Compatibility: -mno-save-restore is default, unless -msave-restore is
// specified.
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
index cd07692be358..5f1638a159d5 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -276,6 +276,8 @@ void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
index 97435f1a73de..3044c2d92d21 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.cpp
@@ -956,6 +956,27 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
CmdArgs.push_back("-fprofile-update=atomic");
}
+ int FunctionGroups = 1;
+ int SelectedFunctionGroup = 0;
+ if (const auto *A = Args.getLastArg(options::OPT_fprofile_function_groups)) {
+ StringRef Val = A->getValue();
+ if (Val.getAsInteger(0, FunctionGroups) || FunctionGroups < 1)
+ D.Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << Val;
+ }
+ if (const auto *A =
+ Args.getLastArg(options::OPT_fprofile_selected_function_group)) {
+ StringRef Val = A->getValue();
+ if (Val.getAsInteger(0, SelectedFunctionGroup) ||
+ SelectedFunctionGroup < 0 || SelectedFunctionGroup >= FunctionGroups)
+ D.Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << Val;
+ }
+ if (FunctionGroups != 1)
+ CmdArgs.push_back(Args.MakeArgString("-fprofile-function-groups=" +
+ Twine(FunctionGroups)));
+ if (SelectedFunctionGroup != 0)
+ CmdArgs.push_back(Args.MakeArgString("-fprofile-selected-function-group=" +
+ Twine(SelectedFunctionGroup)));
+
// Leave -fprofile-dir= an unused argument unless .gcda emission is
// enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider
// the flag used. There is no -fno-profile-dir, so the user has no
@@ -1902,18 +1923,11 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
- StringRef Name = A->getValue();
-
- std::string TuneCPU;
- if (Name == "native")
- TuneCPU = std::string(llvm::sys::getHostCPUName());
+ CmdArgs.push_back("-tune-cpu");
+ if (strcmp(A->getValue(), "native") == 0)
+ CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));
else
- TuneCPU = std::string(Name);
-
- if (!TuneCPU.empty()) {
- CmdArgs.push_back("-tune-cpu");
- CmdArgs.push_back(Args.MakeArgString(TuneCPU));
- }
+ CmdArgs.push_back(A->getValue());
}
AddUnalignedAccessWarning(CmdArgs);
@@ -2167,18 +2181,11 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs);
- std::string TuneCPU;
-
- if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
- StringRef Name = A->getValue();
-
- Name = llvm::RISCV::resolveTuneCPUAlias(Name, Triple.isArch64Bit());
- TuneCPU = std::string(Name);
- }
-
- if (!TuneCPU.empty()) {
+ if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
+ StringRef Name =
+ llvm::RISCV::resolveTuneCPUAlias(A->getValue(), Triple.isArch64Bit());
CmdArgs.push_back("-tune-cpu");
- CmdArgs.push_back(Args.MakeArgString(TuneCPU));
+ CmdArgs.push_back(Name.data());
}
}
@@ -2202,19 +2209,12 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
void Clang::AddSystemZTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
- if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
- StringRef Name = A->getValue();
-
- std::string TuneCPU;
- if (Name == "native")
- TuneCPU = std::string(llvm::sys::getHostCPUName());
+ if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
+ CmdArgs.push_back("-tune-cpu");
+ if (strcmp(A->getValue(), "native") == 0)
+ CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));
else
- TuneCPU = std::string(Name);
-
- if (!TuneCPU.empty()) {
- CmdArgs.push_back("-tune-cpu");
- CmdArgs.push_back(Args.MakeArgString(TuneCPU));
- }
+ CmdArgs.push_back(A->getValue());
}
bool HasBackchain =
@@ -3490,6 +3490,7 @@ static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
types::ID InputType) {
const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version,
options::OPT_D,
+ options::OPT_I,
options::OPT_S,
options::OPT_emit_llvm,
options::OPT_disable_llvm_passes,
@@ -3985,6 +3986,9 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
+ if (StringRef(A->getValue()) == "sarif" ||
+ StringRef(A->getValue()) == "SARIF")
+ D.Diag(diag::warn_drv_sarif_format_unstable);
}
if (const Arg *A = Args.getLastArg(
@@ -4030,9 +4034,7 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
options::OPT_fno_spell_checking);
}
-enum class DwarfFissionKind { None, Split, Single };
-
-static DwarfFissionKind getDebugFissionKind(const Driver &D,
+DwarfFissionKind tools::getDebugFissionKind(const Driver &D,
const ArgList &Args, Arg *&Arg) {
Arg = Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ,
options::OPT_gno_split_dwarf);
@@ -5388,9 +5390,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind());
- // FIXME: Handle -mtune=.
- (void)Args.hasArg(options::OPT_mtune_EQ);
-
if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
StringRef CM = A->getValue();
if (CM == "small" || CM == "kernel" || CM == "medium" || CM == "large" ||
@@ -5837,12 +5836,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
- if (Args.hasArg(options::OPT_funstable)) {
- CmdArgs.push_back("-funstable");
- if (!Args.hasArg(options::OPT_fno_coroutines_ts))
- CmdArgs.push_back("-fcoroutines-ts");
- CmdArgs.push_back("-fmodules-ts");
- }
+ Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
CmdArgs.push_back("-fexperimental-new-constant-interpreter");
@@ -6209,6 +6203,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_ftime_report_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace);
Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ);
+ Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_EQ);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
Args.AddLastArg(CmdArgs, options::OPT_malign_double);
Args.AddLastArg(CmdArgs, options::OPT_fno_temp_file);
@@ -6243,6 +6238,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
options::OPT_fno_unroll_loops);
+ Args.AddLastArg(CmdArgs, options::OPT_fstrict_flex_arrays_EQ);
+
Args.AddLastArg(CmdArgs, options::OPT_pthread);
if (Args.hasFlag(options::OPT_mspeculative_load_hardening,
@@ -6986,7 +6983,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fcuda-include-gpubinary");
CmdArgs.push_back(CudaDeviceInput->getFilename());
} else if (!HostOffloadingInputs.empty()) {
- if (IsCuda && !IsRDCMode) {
+ if ((IsCuda || IsHIP) && !IsRDCMode) {
assert(HostOffloadingInputs.size() == 1 && "Only one input expected");
CmdArgs.push_back("-fcuda-include-gpubinary");
CmdArgs.push_back(HostOffloadingInputs.front().getFilename());
@@ -8448,14 +8445,14 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
// Forward remarks passes to the LLVM backend in the wrapper.
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
- CmdArgs.push_back(
- Args.MakeArgString(Twine("--pass-remarks=") + A->getValue()));
+ CmdArgs.push_back(Args.MakeArgString(Twine("--offload-opt=-pass-remarks=") +
+ A->getValue()));
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ))
- CmdArgs.push_back(
- Args.MakeArgString(Twine("--pass-remarks-missed=") + A->getValue()));
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("--offload-opt=-pass-remarks-missed=") + A->getValue()));
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
- CmdArgs.push_back(
- Args.MakeArgString(Twine("--pass-remarks-analysis=") + A->getValue()));
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("--offload-opt=-pass-remarks-analysis=") + A->getValue()));
if (Args.getLastArg(options::OPT_save_temps_EQ))
CmdArgs.push_back("--save-temps");
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h
index 37263efd57a5..5209c6687599 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Clang.h
@@ -198,6 +198,12 @@ public:
const char *LinkingOutput) const override;
};
+enum class DwarfFissionKind { None, Split, Single };
+
+DwarfFissionKind getDebugFissionKind(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::Arg *&Arg);
+
} // end namespace tools
} // end namespace driver
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp
index 501e3a382ec1..9fd0529a3297 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CloudABI.cpp
@@ -117,6 +117,8 @@ void CloudABI::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp
index 2b043fbeecda..681a6824dad1 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp
@@ -273,8 +273,11 @@ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
void CrossWindowsToolChain::
AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
- if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
+ if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
+ }
}
clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
index c9e773701ac3..bada811daadf 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1141,25 +1141,38 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args,
SmallString<128> P(getDriver().ClangExecutable);
llvm::sys::path::remove_filename(P); // 'clang'
llvm::sys::path::remove_filename(P); // 'bin'
+ llvm::sys::path::append(P, "lib", "arc");
// 'libarclite' usually lives in the same toolchain as 'clang'. However, the
// Swift open source toolchains for macOS distribute Clang without libarclite.
// In that case, to allow the linker to find 'libarclite', we point to the
// 'libarclite' in the XcodeDefault toolchain instead.
- if (getXcodeDeveloperPath(P).empty()) {
- if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ if (!getVFS().exists(P)) {
+ auto updatePath = [&](const Arg *A) {
// Try to infer the path to 'libarclite' in the toolchain from the
// specified SDK path.
StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
- if (!XcodePathForSDK.empty()) {
- P = XcodePathForSDK;
- llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr");
- }
+ if (XcodePathForSDK.empty())
+ return false;
+
+ P = XcodePathForSDK;
+ llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",
+ "lib", "arc");
+ return getVFS().exists(P);
+ };
+
+ bool updated = false;
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot))
+ updated = updatePath(A);
+
+ if (!updated) {
+ if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
+ updatePath(A);
}
}
CmdArgs.push_back("-force_load");
- llvm::sys::path::append(P, "lib", "arc", "libarclite_");
+ llvm::sys::path::append(P, "libarclite_");
// Mash in the platform.
if (isTargetWatchOSSimulator())
P += "watchsimulator";
@@ -2448,6 +2461,7 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
break;
}
}
+
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
@@ -2455,6 +2469,8 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp
index 8cfec6a6c4e0..ba901407715f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -69,7 +69,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-Bshareable");
- else {
+ else if (!Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld-elf.so.2");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 79e3c5cbca5f..e5451c20a00c 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -170,7 +170,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
- } else {
+ } else if (!Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld-elf.so.1");
}
@@ -389,10 +389,10 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
// back to '/usr/lib' if it doesn't exist.
if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() ||
Triple.isPPC32()) &&
- D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
- getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
+ D.getVFS().exists(concat(getDriver().SysRoot, "/usr/lib32/crt1.o")))
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib32"));
else
- getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
@@ -411,14 +411,14 @@ unsigned FreeBSD::GetDefaultDwarfVersion() const {
void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/v1");
+ concat(getDriver().SysRoot, "/usr/include/c++/v1"));
}
void FreeBSD::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
- addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/c++/4.2", "", "",
- DriverArgs, CC1Args);
+ addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/c++/4.2"),
+ "", "", DriverArgs, CC1Args);
}
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
@@ -430,6 +430,8 @@ void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 03ff9fe894c8..d63c69c63b1f 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -101,7 +101,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);
- if (!Args.hasArg(options::OPT_shared)) {
+ if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) {
std::string Dyld = D.DyldPrefix;
if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt())
Dyld += "asan/";
@@ -417,6 +417,8 @@ void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
index ed07e710fc49..93b987c07f29 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -614,6 +614,8 @@ void HexagonToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
break;
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp
index 41b7b839f3b3..9c58583bca77 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/MipsLinux.cpp
@@ -112,6 +112,8 @@ void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
"Only -lc++ (aka libxx) is supported in this toolchain.");
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
index 753459cb230b..38151735ee51 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/NaCl.cpp
@@ -308,6 +308,8 @@ void NaClToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
// if the value is libc++, and emits an error for other values.
GetCXXStdlibType(Args);
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
}
void NaClToolChain::addLibCxxIncludePaths(
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
index d1eda14a51f0..ac90ed49b8a5 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -139,7 +139,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
- } else {
+ } else if (!Args.hasArg(options::OPT_r)) {
Args.AddAllArgs(CmdArgs, options::OPT_pie);
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld.elf_so");
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 54cf3cc89caf..8b3a40606ff3 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -147,7 +147,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-Bdynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-shared");
- } else {
+ } else if (!Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/usr/libexec/ld.so");
}
@@ -284,7 +284,7 @@ SanitizerMask OpenBSD::getSupportedSanitizers() const {
OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
- getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
void OpenBSD::AddClangSystemIncludeArgs(
@@ -317,13 +317,14 @@ void OpenBSD::AddClangSystemIncludeArgs(
return;
}
- addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include");
+ addExternCSystemInclude(DriverArgs, CC1Args,
+ concat(D.SysRoot, "/usr/include"));
}
void OpenBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/v1");
+ concat(getDriver().SysRoot, "/usr/include/c++/v1"));
}
void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
@@ -331,6 +332,8 @@ void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
bool Profiling = Args.hasArg(options::OPT_pg);
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi");
CmdArgs.push_back(Profiling ? "-lpthread_p" : "-lpthread");
}
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp
index 1e43796be1ff..9be239262db8 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/VEToolchain.cpp
@@ -141,6 +141,8 @@ void VEToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
tools::addArchSpecificRPath(*this, Args, CmdArgs);
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
CmdArgs.push_back("-lunwind");
// libc++ requires -lpthread under glibc environment
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
index c5e4d569793c..b051bff87512 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -444,6 +444,8 @@ void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:
diff --git a/contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index bffa66c2d944..1a785182e363 100644
--- a/contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/contrib/llvm-project/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -303,6 +303,7 @@ public:
// Skip templated functions.
switch (Decl->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
+ case FunctionDecl::TK_DependentNonTemplate:
break;
case FunctionDecl::TK_MemberSpecialization:
case FunctionDecl::TK_FunctionTemplateSpecialization:
diff --git a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
index 1cd28ab073da..651ec80d6196 100644
--- a/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
+++ b/contrib/llvm-project/clang/lib/Format/ContinuationIndenter.cpp
@@ -37,7 +37,7 @@ static bool shouldIndentWrappedSelectorName(const FormatStyle &Style,
// Returns the length of everything up to the first possible line break after
// the ), ], } or > matching \c Tok.
static unsigned getLengthToMatchingParen(const FormatToken &Tok,
- const SmallVector<ParenState> &Stack) {
+ ArrayRef<ParenState> Stack) {
// Normally whether or not a break before T is possible is calculated and
// stored in T.CanBreakBefore. Braces, array initializers and text proto
// messages like `key: < ... >` are an exception: a break is possible
@@ -656,6 +656,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
int PPColumnCorrection = 0;
if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash &&
Previous.is(tok::hash) && State.FirstIndent > 0 &&
+ &Previous == State.Line->First &&
(State.Line->Type == LT_PreprocessorDirective ||
State.Line->Type == LT_ImportStatement)) {
Spaces += State.FirstIndent;
@@ -1190,6 +1191,10 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
break;
}
}
+ if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
+ TT_InheritanceComma)) {
+ return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
+ }
if ((PreviousNonComment &&
(PreviousNonComment->ClosesTemplateDeclaration ||
PreviousNonComment->ClosesRequiresClause ||
@@ -1264,10 +1269,6 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
Style.BreakInheritanceList == FormatStyle::BILS_AfterColon) {
return CurrentState.Indent;
}
- if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
- TT_InheritanceComma)) {
- return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
- }
if (Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
!Current.isOneOf(tok::colon, tok::comment)) {
return ContinuationIndent;
diff --git a/contrib/llvm-project/clang/lib/Format/Format.cpp b/contrib/llvm-project/clang/lib/Format/Format.cpp
index d13907faca43..2659fa2af1a7 100644
--- a/contrib/llvm-project/clang/lib/Format/Format.cpp
+++ b/contrib/llvm-project/clang/lib/Format/Format.cpp
@@ -1895,26 +1895,31 @@ private:
void removeBraces(SmallVectorImpl<AnnotatedLine *> &Lines,
tooling::Replacements &Result) {
const auto &SourceMgr = Env.getSourceManager();
+ bool EndsWithComment = false;
for (AnnotatedLine *Line : Lines) {
removeBraces(Line->Children, Result);
- if (!Line->Affected)
- continue;
- for (FormatToken *Token = Line->First; Token && !Token->Finalized;
- Token = Token->Next) {
- if (!Token->Optional)
- continue;
- assert(Token->isOneOf(tok::l_brace, tok::r_brace));
- assert(Token->Next || Token == Line->Last);
- const auto Start =
- Token == Line->Last ||
- (Token->Next->isOneOf(tok::kw_else, tok::comment) &&
- Token->Next->NewlinesBefore > 0)
- ? Token->WhitespaceRange.getBegin()
- : Token->Tok.getLocation();
- const auto Range =
- CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
- cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
+ if (Line->Affected) {
+ for (FormatToken *Token = Line->First; Token && !Token->Finalized;
+ Token = Token->Next) {
+ if (!Token->Optional)
+ continue;
+ assert(Token->isOneOf(tok::l_brace, tok::r_brace));
+ assert(Token->Previous || Token == Line->First);
+ const FormatToken *Next = Token->Next;
+ assert(Next || Token == Line->Last);
+ const auto Start =
+ (!Token->Previous && EndsWithComment) ||
+ (Next && !(Next->isOneOf(tok::kw_else, tok::comment) &&
+ Next->NewlinesBefore > 0))
+ ? Token->Tok.getLocation()
+ : Token->WhitespaceRange.getBegin();
+ const auto Range =
+ CharSourceRange::getCharRange(Start, Token->Tok.getEndLoc());
+ cantFail(Result.add(tooling::Replacement(SourceMgr, Range, "")));
+ }
}
+ assert(Line->Last);
+ EndsWithComment = Line->Last->is(tok::comment);
}
}
};
diff --git a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
index 98c012994f45..5991cf23d5dc 100644
--- a/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
+++ b/contrib/llvm-project/clang/lib/Format/TokenAnnotator.cpp
@@ -999,7 +999,8 @@ private:
FormatToken *Prev = Tok->getPreviousNonComment();
if (!Prev)
break;
- if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept)) {
+ if (Prev->isOneOf(tok::r_paren, tok::kw_noexcept) ||
+ Prev->ClosesRequiresClause) {
Tok->setType(TT_CtorInitializerColon);
} else if (Prev->is(tok::kw_try)) {
// Member initializer list within function try block.
@@ -2317,7 +2318,15 @@ private:
// After right braces, star tokens are likely to be pointers to struct,
// union, or class.
// struct {} *ptr;
- if (PrevToken->is(tok::r_brace) && Tok.is(tok::star))
+ // This by itself is not sufficient to distinguish from multiplication
+ // following a brace-initialized expression, as in:
+ // int i = int{42} * 2;
+ // In the struct case, the part of the struct declaration until the `{` and
+ // the `}` are put on separate unwrapped lines; in the brace-initialized
+ // case, the matching `{` is on the same unwrapped line, so check for the
+ // presence of the matching brace to distinguish between those.
+ if (PrevToken->is(tok::r_brace) && Tok.is(tok::star) &&
+ !PrevToken->MatchingParen)
return TT_PointerOrReference;
// For "} &&"
diff --git a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
index 97c3d86282a0..83b4f1e7991f 100644
--- a/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/contrib/llvm-project/clang/lib/Format/UnwrappedLineParser.cpp
@@ -539,7 +539,7 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace,
break;
case tok::r_brace:
if (OpeningBrace) {
- if (!Style.RemoveBracesLLVM ||
+ if (!Style.RemoveBracesLLVM || Line->InPPDirective ||
!OpeningBrace->isOneOf(TT_ControlStatementLBrace, TT_ElseLBrace)) {
return false;
}
@@ -2119,6 +2119,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
case tok::amp:
case tok::star:
case tok::kw_const:
+ case tok::kw_constexpr:
case tok::comma:
case tok::less:
case tok::greater:
diff --git a/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp b/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp
index ed3e314cc73b..7b07ab948f64 100644
--- a/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp
+++ b/contrib/llvm-project/clang/lib/Frontend/FrontendAction.cpp
@@ -414,7 +414,7 @@ static std::error_code collectModuleHeaderIncludes(
// Sort header paths and make the header inclusion order deterministic
// across different OSs and filesystems.
- llvm::sort(Headers.begin(), Headers.end(), llvm::less_first());
+ llvm::sort(Headers, llvm::less_first());
for (auto &H : Headers) {
// Include this header as part of the umbrella directory.
Module->addTopHeader(H.second);
@@ -1205,4 +1205,3 @@ bool WrapperFrontendAction::hasCodeCompletionSupport() const {
WrapperFrontendAction::WrapperFrontendAction(
std::unique_ptr<FrontendAction> WrappedAction)
: WrappedAction(std::move(WrappedAction)) {}
-
diff --git a/contrib/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp b/contrib/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp
index d0360696ff9c..20bfbf144a30 100644
--- a/contrib/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/contrib/llvm-project/clang/lib/Frontend/InitPreprocessor.cpp
@@ -298,12 +298,12 @@ static void DefineFastIntType(unsigned TypeWidth, bool IsSigned,
/// Get the value the ATOMIC_*_LOCK_FREE macro should have for a type with
/// the specified properties.
-static const char *getLockFreeValue(unsigned TypeWidth, unsigned TypeAlign,
- unsigned InlineWidth) {
+static const char *getLockFreeValue(unsigned TypeWidth, unsigned InlineWidth) {
// Fully-aligned, power-of-2 sizes no larger than the inline
// width will be inlined as lock-free operations.
- if (TypeWidth == TypeAlign && (TypeWidth & (TypeWidth - 1)) == 0 &&
- TypeWidth <= InlineWidth)
+ // Note: we do not need to check alignment since _Atomic(T) is always
+ // appropriately-aligned in clang.
+ if ((TypeWidth & (TypeWidth - 1)) == 0 && TypeWidth <= InlineWidth)
return "2"; // "always lock free"
// We cannot be certain what operations the lib calls might be
// able to implement as lock-free on future processors.
@@ -829,15 +829,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::ObjFW) {
VersionTuple tuple = LangOpts.ObjCRuntime.getVersion();
-
- unsigned minor = 0;
- if (tuple.getMinor())
- minor = tuple.getMinor().value();
-
- unsigned subminor = 0;
- if (tuple.getSubminor())
- subminor = tuple.getSubminor().value();
-
+ unsigned minor = tuple.getMinor().value_or(0);
+ unsigned subminor = tuple.getSubminor().value_or(0);
Builder.defineMacro("__OBJFW_RUNTIME_ABI__",
Twine(tuple.getMajor() * 10000 + minor * 100 +
subminor));
@@ -1149,7 +1142,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
#define DEFINE_LOCK_FREE_MACRO(TYPE, Type) \
Builder.defineMacro(Prefix + #TYPE "_LOCK_FREE", \
getLockFreeValue(TI.get##Type##Width(), \
- TI.get##Type##Align(), \
InlineWidthBits));
DEFINE_LOCK_FREE_MACRO(BOOL, Bool);
DEFINE_LOCK_FREE_MACRO(CHAR, Char);
@@ -1164,7 +1156,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DEFINE_LOCK_FREE_MACRO(LLONG, LongLong);
Builder.defineMacro(Prefix + "POINTER_LOCK_FREE",
getLockFreeValue(TI.getPointerWidth(0),
- TI.getPointerAlign(0),
InlineWidthBits));
#undef DEFINE_LOCK_FREE_MACRO
};
diff --git a/contrib/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp b/contrib/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp
index 6c0ea0cde358..ab0dbcef6534 100644
--- a/contrib/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/contrib/llvm-project/clang/lib/Frontend/TextDiagnostic.cpp
@@ -815,6 +815,7 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
emitFilename(PLoc.getFilename(), Loc.getManager());
switch (DiagOpts->getFormat()) {
+ case DiagnosticOptions::SARIF:
case DiagnosticOptions::Clang:
if (DiagOpts->ShowLine)
OS << ':' << LineNo;
@@ -837,6 +838,7 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
OS << ColNo;
}
switch (DiagOpts->getFormat()) {
+ case DiagnosticOptions::SARIF:
case DiagnosticOptions::Clang:
case DiagnosticOptions::Vi: OS << ':'; break;
case DiagnosticOptions::MSVC:
diff --git a/contrib/llvm-project/clang/lib/Headers/__clang_cuda_intrinsics.h b/contrib/llvm-project/clang/lib/Headers/__clang_cuda_intrinsics.h
index cfd5eb869e34..b87413e12a27 100644
--- a/contrib/llvm-project/clang/lib/Headers/__clang_cuda_intrinsics.h
+++ b/contrib/llvm-project/clang/lib/Headers/__clang_cuda_intrinsics.h
@@ -71,8 +71,8 @@
} \
inline __device__ unsigned long long __FnName( \
unsigned long long __val, __Type __offset, int __width = warpSize) { \
- return static_cast<unsigned long long>(::__FnName( \
- static_cast<unsigned long long>(__val), __offset, __width)); \
+ return static_cast<unsigned long long>( \
+ ::__FnName(static_cast<long long>(__val), __offset, __width)); \
} \
inline __device__ double __FnName(double __val, __Type __offset, \
int __width = warpSize) { \
@@ -139,8 +139,8 @@ __MAKE_SHUFFLES(__shfl_xor, __nvvm_shfl_bfly_i32, __nvvm_shfl_bfly_f32, 0x1f,
inline __device__ unsigned long long __FnName( \
unsigned int __mask, unsigned long long __val, __Type __offset, \
int __width = warpSize) { \
- return static_cast<unsigned long long>(::__FnName( \
- __mask, static_cast<unsigned long long>(__val), __offset, __width)); \
+ return static_cast<unsigned long long>( \
+ ::__FnName(__mask, static_cast<long long>(__val), __offset, __width)); \
} \
inline __device__ long __FnName(unsigned int __mask, long __val, \
__Type __offset, int __width = warpSize) { \
diff --git a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/emmintrin.h b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/emmintrin.h
index 8c6aa23c1a0d..a4c458a41bcf 100644
--- a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/emmintrin.h
+++ b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/emmintrin.h
@@ -36,7 +36,8 @@
#ifndef EMMINTRIN_H_
#define EMMINTRIN_H_
-#if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
+#if defined(__ppc64__) && \
+ (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX))
#include <altivec.h>
@@ -2261,7 +2262,7 @@ extern __inline __m128d
#else
#include_next <emmintrin.h>
-#endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
- */
+#endif /* defined(__ppc64__) &&
+ * (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX)) */
#endif /* EMMINTRIN_H_ */
diff --git a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mm_malloc.h b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mm_malloc.h
index 29c1de4a83e1..65920917f3bd 100644
--- a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mm_malloc.h
+++ b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mm_malloc.h
@@ -10,7 +10,8 @@
#ifndef _MM_MALLOC_H_INCLUDED
#define _MM_MALLOC_H_INCLUDED
-#if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
+#if defined(__ppc64__) && \
+ (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX))
#include <stdlib.h>
diff --git a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mmintrin.h b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mmintrin.h
index 6f9c137b6a09..70e8b81e11ee 100644
--- a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mmintrin.h
+++ b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/mmintrin.h
@@ -35,7 +35,8 @@
#ifndef _MMINTRIN_H_INCLUDED
#define _MMINTRIN_H_INCLUDED
-#if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
+#if defined(__ppc64__) && \
+ (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX))
#include <altivec.h>
/* The Intel API is flexible enough that we must allow aliasing with other
@@ -1446,7 +1447,7 @@ extern __inline __m64
#else
#include_next <mmintrin.h>
-#endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
- */
+#endif /* defined(__ppc64__) &&
+ * (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX)) */
#endif /* _MMINTRIN_H_INCLUDED */
diff --git a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/pmmintrin.h b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/pmmintrin.h
index 889f57ae89d8..fda39edbaa22 100644
--- a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/pmmintrin.h
+++ b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/pmmintrin.h
@@ -39,7 +39,8 @@
#ifndef PMMINTRIN_H_
#define PMMINTRIN_H_
-#if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
+#if defined(__ppc64__) && \
+ (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX))
/* We need definitions from the SSE2 and SSE header files*/
#include <emmintrin.h>
@@ -138,7 +139,7 @@ extern __inline __m128i
#else
#include_next <pmmintrin.h>
-#endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
- */
+#endif /* defined(__ppc64__) &&
+ * (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX)) */
#endif /* PMMINTRIN_H_ */
diff --git a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/smmintrin.h b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/smmintrin.h
index 694d5aa06940..6fe6c8a93d9b 100644
--- a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/smmintrin.h
+++ b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/smmintrin.h
@@ -29,7 +29,8 @@
#ifndef SMMINTRIN_H_
#define SMMINTRIN_H_
-#if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
+#if defined(__ppc64__) && \
+ (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX))
#include <altivec.h>
#include <tmmintrin.h>
@@ -656,7 +657,7 @@ extern __inline __m128i
#else
#include_next <smmintrin.h>
-#endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
- */
+#endif /* defined(__ppc64__) &&
+ * (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX)) */
#endif /* SMMINTRIN_H_ */
diff --git a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/tmmintrin.h b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/tmmintrin.h
index 1725eb9b8f64..6185ca1e7e71 100644
--- a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/tmmintrin.h
+++ b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/tmmintrin.h
@@ -25,7 +25,8 @@
#ifndef TMMINTRIN_H_
#define TMMINTRIN_H_
-#if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
+#if defined(__ppc64__) && \
+ (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX))
#include <altivec.h>
@@ -446,7 +447,7 @@ extern __inline __m64
#else
#include_next <tmmintrin.h>
-#endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
- */
+#endif /* defined(__ppc64__) &&
+ * (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX)) */
#endif /* TMMINTRIN_H_ */
diff --git a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/xmmintrin.h b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/xmmintrin.h
index 8bf29777b79c..ee0032ca159c 100644
--- a/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/xmmintrin.h
+++ b/contrib/llvm-project/clang/lib/Headers/ppc_wrappers/xmmintrin.h
@@ -35,7 +35,8 @@
#ifndef XMMINTRIN_H_
#define XMMINTRIN_H_
-#if defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__))
+#if defined(__ppc64__) && \
+ (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX))
/* Define four value permute mask */
#define _MM_SHUFFLE(w, x, y, z) (((w) << 6) | ((x) << 4) | ((y) << 2) | (z))
@@ -1820,7 +1821,7 @@ extern __inline void
#else
#include_next <xmmintrin.h>
-#endif /* defined(__ppc64__) && (defined(__linux__) || defined(__FreeBSD__)) \
- */
+#endif /* defined(__ppc64__) &&
+ * (defined(__linux__) || defined(__FreeBSD__) || defined(_AIX)) */
#endif /* XMMINTRIN_H_ */
diff --git a/contrib/llvm-project/clang/lib/Headers/x86gprintrin.h b/contrib/llvm-project/clang/lib/Headers/x86gprintrin.h
index 01e741f1eb61..2c2fbb97c9ac 100644
--- a/contrib/llvm-project/clang/lib/Headers/x86gprintrin.h
+++ b/contrib/llvm-project/clang/lib/Headers/x86gprintrin.h
@@ -25,11 +25,29 @@
#include <crc32intrin.h>
#endif
-#define __SSC_MARK(Tag) \
- __asm__ __volatile__("mov {%%ebx, %%eax|eax, ebx}; " \
- "mov {%0, %%ebx|ebx, %0}; " \
+#if defined(__i386__)
+#define __FULLBX "ebx"
+#define __TMPGPR "eax"
+#else
+// When in 64-bit target, the 32-bit operands generate a 32-bit result,
+// zero-extended to a 64-bit result in the destination general-purpose,
+// It means "mov x %ebx" will clobber the higher 32 bits of rbx, so we
+// should preserve the 64-bit register rbx.
+#define __FULLBX "rbx"
+#define __TMPGPR "rax"
+#endif
+
+#define __MOVEGPR(__r1, __r2) "mov {%%"__r1 ", %%"__r2 "|"__r2 ", "__r1"};"
+
+#define __SAVE_GPRBX __MOVEGPR(__FULLBX, __TMPGPR)
+#define __RESTORE_GPRBX __MOVEGPR(__TMPGPR, __FULLBX)
+
+#define __SSC_MARK(__Tag) \
+ __asm__ __volatile__( __SAVE_GPRBX \
+ "mov {%0, %%ebx|ebx, %0}; " \
".byte 0x64, 0x67, 0x90; " \
- "mov {%%eax, %%ebx|ebx, eax};" ::"i"(Tag) \
- : "%eax");
+ __RESTORE_GPRBX \
+ ::"i"(__Tag) \
+ : __TMPGPR );
#endif /* __X86GPRINTRIN_H */
diff --git a/contrib/llvm-project/clang/lib/Lex/Lexer.cpp b/contrib/llvm-project/clang/lib/Lex/Lexer.cpp
index b3aac9df6546..a4cff403e739 100644
--- a/contrib/llvm-project/clang/lib/Lex/Lexer.cpp
+++ b/contrib/llvm-project/clang/lib/Lex/Lexer.cpp
@@ -1462,11 +1462,11 @@ static bool isAllowedIDChar(uint32_t C, const LangOptions &LangOpts) {
return false;
} else if (LangOpts.DollarIdents && '$' == C) {
return true;
- } else if (LangOpts.CPlusPlus) {
+ } else if (LangOpts.CPlusPlus || LangOpts.C2x) {
// A non-leading codepoint must have the XID_Continue property.
// XIDContinueRanges doesn't contains characters also in XIDStartRanges,
// so we need to check both tables.
- // '_' doesn't have the XID_Continue property but is allowed in C++.
+ // '_' doesn't have the XID_Continue property but is allowed in C and C++.
static const llvm::sys::UnicodeCharSet XIDStartChars(XIDStartRanges);
static const llvm::sys::UnicodeCharSet XIDContinueChars(XIDContinueRanges);
return C == '_' || XIDStartChars.contains(C) ||
@@ -1486,7 +1486,7 @@ static bool isAllowedInitiallyIDChar(uint32_t C, const LangOptions &LangOpts) {
if (LangOpts.AsmPreprocessor) {
return false;
}
- if (LangOpts.CPlusPlus) {
+ if (LangOpts.CPlusPlus || LangOpts.C2x) {
static const llvm::sys::UnicodeCharSet XIDStartChars(XIDStartRanges);
// '_' doesn't have the XID_Start property but is allowed in C++.
return C == '_' || XIDStartChars.contains(C);
diff --git a/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp b/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp
index 57e344622f25..47d6f5893e97 100644
--- a/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp
+++ b/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp
@@ -456,10 +456,8 @@ static bool violatesPrivateInclude(Module *RequestingModule,
&Header.getModule()->Headers[Module::HK_Private],
&Header.getModule()->Headers[Module::HK_PrivateTextual]};
for (auto *Hs : HeaderList)
- IsPrivate |=
- std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
- return H.Entry == IncFileEnt;
- }) != Hs->end();
+ IsPrivate |= llvm::any_of(
+ *Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
assert(IsPrivate && "inconsistent headers and roles");
}
#endif
diff --git a/contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp b/contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp
index 352e1f217819..9a8fd4391b41 100644
--- a/contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp
+++ b/contrib/llvm-project/clang/lib/Lex/PPDirectives.cpp
@@ -1261,7 +1261,16 @@ void Preprocessor::HandleDirective(Token &Result) {
return HandleIncludeNextDirective(SavedHash.getLocation(), Result);
case tok::pp_warning:
- Diag(Result, diag::ext_pp_warning_directive);
+ if (LangOpts.CPlusPlus)
+ Diag(Result, LangOpts.CPlusPlus2b
+ ? diag::warn_cxx2b_compat_warning_directive
+ : diag::ext_pp_warning_directive)
+ << /*C++2b*/ 1;
+ else
+ Diag(Result, LangOpts.C2x ? diag::warn_c2x_compat_warning_directive
+ : diag::ext_pp_warning_directive)
+ << /*C2x*/ 0;
+
return HandleUserDiagnosticDirective(Result, true);
case tok::pp_ident:
return HandleIdentSCCSDirective(Result);
@@ -1806,22 +1815,14 @@ static void diagnoseAutoModuleImport(
Preprocessor &PP, SourceLocation HashLoc, Token &IncludeTok,
ArrayRef<std::pair<IdentifierInfo *, SourceLocation>> Path,
SourceLocation PathEnd) {
- StringRef ImportKeyword;
- if (PP.getLangOpts().ObjC)
- ImportKeyword = "@import";
- else if (PP.getLangOpts().ModulesTS || PP.getLangOpts().CPlusPlusModules)
- ImportKeyword = "import";
- else
- return; // no import syntax available
-
SmallString<128> PathString;
for (size_t I = 0, N = Path.size(); I != N; ++I) {
if (I)
PathString += '.';
PathString += Path[I].first->getName();
}
- int IncludeKind = 0;
+ int IncludeKind = 0;
switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
IncludeKind = 0;
@@ -1843,12 +1844,8 @@ static void diagnoseAutoModuleImport(
llvm_unreachable("unknown include directive kind");
}
- CharSourceRange ReplaceRange(SourceRange(HashLoc, PathEnd),
- /*IsTokenRange=*/false);
- PP.Diag(HashLoc, diag::warn_auto_module_import)
- << IncludeKind << PathString
- << FixItHint::CreateReplacement(
- ReplaceRange, (ImportKeyword + " " + PathString + ";").str());
+ PP.Diag(HashLoc, diag::remark_pp_include_directive_modular_translation)
+ << IncludeKind << PathString;
}
// Given a vector of path components and a string containing the real
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseAST.cpp b/contrib/llvm-project/clang/lib/Parse/ParseAST.cpp
index 04b3f0460bf3..5fca029a4266 100644
--- a/contrib/llvm-project/clang/lib/Parse/ParseAST.cpp
+++ b/contrib/llvm-project/clang/lib/Parse/ParseAST.cpp
@@ -172,6 +172,29 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
for (Decl *D : S.WeakTopLevelDecls())
Consumer->HandleTopLevelDecl(DeclGroupRef(D));
+ // For C++20 modules, the codegen for module initializers needs to be altered
+ // and to be able to use a name based on the module name.
+
+ // At this point, we should know if we are building a non-header C++20 module.
+ if (S.getLangOpts().CPlusPlusModules && !S.getLangOpts().IsHeaderFile &&
+ !S.getLangOpts().CurrentModule.empty()) {
+ // If we are building the module from source, then the top level module
+ // will be here.
+ Module *CodegenModule = S.getCurrentModule();
+ bool Interface = true;
+ if (CodegenModule)
+ // We only use module initializers for interfaces (including partition
+ // implementation units).
+ Interface = S.currentModuleIsInterface();
+ else
+ // If we are building the module from a PCM file, then the module can be
+ // found here.
+ CodegenModule = S.getPreprocessor().getCurrentModule();
+ // If neither. then ....
+ assert(CodegenModule && "codegen for a module, but don't know which?");
+ if (Interface)
+ S.getASTContext().setModuleForCodeGen(CodegenModule);
+ }
Consumer->HandleTranslationUnit(S.getASTContext());
// Finalize the template instantiation observer chain.
diff --git a/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 164fea6a449b..9780a0aba749 100644
--- a/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1575,8 +1575,7 @@ public:
// Sort the uses by their SourceLocations. While not strictly
// guaranteed to produce them in line/column order, this will provide
// a stable ordering.
- llvm::sort(vec->begin(), vec->end(),
- [](const UninitUse &a, const UninitUse &b) {
+ llvm::sort(*vec, [](const UninitUse &a, const UninitUse &b) {
// Prefer a more confident report over a less confident one.
if (a.getKind() != b.getKind())
return a.getKind() > b.getKind();
diff --git a/contrib/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp
index 8e8a1be38c0f..e93be3e04dfe 100644
--- a/contrib/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -515,7 +515,8 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
case CK_FunctionType:
return Type;
-
+ case CK_FunctionProtoTypeLoc:
+ return ProtoTypeLoc.getTypePtr();
case CK_Template:
case CK_Aggregate:
return nullptr;
@@ -524,6 +525,13 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
llvm_unreachable("Invalid CandidateKind!");
}
+const FunctionProtoTypeLoc
+CodeCompleteConsumer::OverloadCandidate::getFunctionProtoTypeLoc() const {
+ if (Kind == CK_FunctionProtoTypeLoc)
+ return ProtoTypeLoc;
+ return FunctionProtoTypeLoc();
+}
+
unsigned CodeCompleteConsumer::OverloadCandidate::getNumParams() const {
if (Kind == CK_Template)
return Template->getTemplateParameters()->size();
@@ -597,7 +605,12 @@ CodeCompleteConsumer::OverloadCandidate::getParamDecl(unsigned N) const {
if (const auto *FD = getFunction()) {
if (N < FD->param_size())
return FD->getParamDecl(N);
+ } else if (Kind == CK_FunctionProtoTypeLoc) {
+ if (N < ProtoTypeLoc.getNumParams()) {
+ return ProtoTypeLoc.getParam(N);
+ }
}
+
return nullptr;
}
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaCUDA.cpp b/contrib/llvm-project/clang/lib/Sema/SemaCUDA.cpp
index 185ccebe2717..0a49d72ba963 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaCUDA.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaCUDA.cpp
@@ -714,7 +714,7 @@ void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) {
// Do not promote dependent variables since the cotr/dtor/initializer are
// not determined. Do it after instantiation.
if (getLangOpts().CUDAIsDevice && !VD->hasAttr<CUDAConstantAttr>() &&
- !VD->hasAttr<CUDAConstantAttr>() && !VD->hasAttr<CUDASharedAttr>() &&
+ !VD->hasAttr<CUDASharedAttr>() &&
(VD->isFileVarDecl() || VD->isStaticDataMember()) &&
!IsDependentVar(VD) &&
((VD->isConstexpr() || VD->getType().isConstQualified()) &&
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp
index aed1d9befe2b..dae51d0690e6 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaChecking.cpp
@@ -11883,6 +11883,9 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
/// warning if the comparison is not likely to do what the programmer intended.
void Sema::CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
BinaryOperatorKind Opcode) {
+ if (!BinaryOperator::isEqualityOp(Opcode))
+ return;
+
// Match and capture subexpressions such as "(float) X == 0.1".
FloatingLiteral *FPLiteral;
CastExpr *FPCast;
@@ -11918,8 +11921,8 @@ void Sema::CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
// Special case: check for x == x (which is OK).
// Do not emit warnings for such cases.
- if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
- if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
+ if (auto *DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
+ if (auto *DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
if (DRL->getDecl() == DRR->getDecl())
return;
@@ -15827,11 +15830,26 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
/// We avoid emitting out-of-bounds access warnings for such arrays as they are
/// commonly used to emulate flexible arrays in C89 code.
static bool IsTailPaddedMemberArray(Sema &S, const llvm::APInt &Size,
- const NamedDecl *ND) {
- if (Size != 1 || !ND) return false;
+ const NamedDecl *ND,
+ unsigned StrictFlexArraysLevel) {
+ if (!ND)
+ return false;
+
+ if (StrictFlexArraysLevel >= 2 && Size != 0)
+ return false;
+
+ if (StrictFlexArraysLevel == 1 && Size.ule(1))
+ return false;
+
+ // FIXME: While the default -fstrict-flex-arrays=0 permits Size>1 trailing
+ // arrays to be treated as flexible-array-members, we still emit diagnostics
+ // as if they are not. Pending further discussion...
+ if (StrictFlexArraysLevel == 0 && Size != 1)
+ return false;
const FieldDecl *FD = dyn_cast<FieldDecl>(ND);
- if (!FD) return false;
+ if (!FD)
+ return false;
// Don't consider sizes resulting from macro expansions or template argument
// substitution to form C89 tail-padded arrays.
@@ -15854,10 +15872,13 @@ static bool IsTailPaddedMemberArray(Sema &S, const llvm::APInt &Size,
}
const RecordDecl *RD = dyn_cast<RecordDecl>(FD->getDeclContext());
- if (!RD) return false;
- if (RD->isUnion()) return false;
+ if (!RD)
+ return false;
+ if (RD->isUnion())
+ return false;
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- if (!CRD->isStandardLayout()) return false;
+ if (!CRD->isStandardLayout())
+ return false;
}
// See if this is the last field decl in the record.
@@ -15985,9 +16006,14 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
// example). In this case we have no information about whether the array
// access exceeds the array bounds. However we can still diagnose an array
// access which precedes the array bounds.
+ //
+ // FIXME: this check should be redundant with the IsUnboundedArray check
+ // above.
if (BaseType->isIncompleteType())
return;
+ // FIXME: this check should belong to the IsTailPaddedMemberArray call
+ // below.
llvm::APInt size = ArrayTy->getSize();
if (!size.isStrictlyPositive())
return;
@@ -16020,10 +16046,9 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
if (AllowOnePastEnd ? index.ule(size) : index.ult(size))
return;
- // Also don't warn for arrays of size 1 which are members of some
- // structure. These are often used to approximate flexible arrays in C89
- // code.
- if (IsTailPaddedMemberArray(*this, size, ND))
+ // Also don't warn for Flexible Array Member emulation.
+ const unsigned StrictFlexArraysLevel = getLangOpts().StrictFlexArrays;
+ if (IsTailPaddedMemberArray(*this, size, ND, StrictFlexArraysLevel))
return;
// Suppress the warning if the subscript expression (as identified by the
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
index 86bad736227d..8ede7c015315 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
@@ -53,6 +53,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+
#include <list>
#include <map>
#include <string>
@@ -3722,13 +3723,11 @@ static void AddOverloadAggregateChunks(const RecordDecl *RD,
/// Add function overload parameter chunks to the given code completion
/// string.
-static void AddOverloadParameterChunks(ASTContext &Context,
- const PrintingPolicy &Policy,
- const FunctionDecl *Function,
- const FunctionProtoType *Prototype,
- CodeCompletionBuilder &Result,
- unsigned CurrentArg, unsigned Start = 0,
- bool InOptional = false) {
+static void AddOverloadParameterChunks(
+ ASTContext &Context, const PrintingPolicy &Policy,
+ const FunctionDecl *Function, const FunctionProtoType *Prototype,
+ FunctionProtoTypeLoc PrototypeLoc, CodeCompletionBuilder &Result,
+ unsigned CurrentArg, unsigned Start = 0, bool InOptional = false) {
if (!Function && !Prototype) {
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
return;
@@ -3747,8 +3746,9 @@ static void AddOverloadParameterChunks(ASTContext &Context,
if (!FirstParameter)
Opt.AddChunk(CodeCompletionString::CK_Comma);
// Optional sections are nested.
- AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
- CurrentArg, P, /*InOptional=*/true);
+ AddOverloadParameterChunks(Context, Policy, Function, Prototype,
+ PrototypeLoc, Opt, CurrentArg, P,
+ /*InOptional=*/true);
Result.AddOptionalChunk(Opt.TakeString());
return;
}
@@ -3762,8 +3762,10 @@ static void AddOverloadParameterChunks(ASTContext &Context,
// Format the placeholder string.
std::string Placeholder;
- if (Function) {
- const ParmVarDecl *Param = Function->getParamDecl(P);
+ assert(P < Prototype->getNumParams());
+ if (Function || PrototypeLoc) {
+ const ParmVarDecl *Param =
+ Function ? Function->getParamDecl(P) : PrototypeLoc.getParam(P);
Placeholder = FormatFunctionParameter(Policy, Param);
if (Param->hasDefaultArg())
Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
@@ -3916,8 +3918,8 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
if (getKind() == CK_Aggregate)
AddOverloadAggregateChunks(getAggregate(), Policy, Result, CurrentArg);
else
- AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
- CurrentArg);
+ AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto,
+ getFunctionProtoTypeLoc(), Result, CurrentArg);
Result.AddChunk(Braced ? CodeCompletionString::CK_RightBrace
: CodeCompletionString::CK_RightParen);
@@ -5998,6 +6000,39 @@ ProduceSignatureHelp(Sema &SemaRef, MutableArrayRef<ResultCandidate> Candidates,
return getParamType(SemaRef, Candidates, CurrentArg);
}
+// Given a callee expression `Fn`, if the call is through a function pointer,
+// try to find the declaration of the corresponding function pointer type,
+// so that we can recover argument names from it.
+static FunctionProtoTypeLoc GetPrototypeLoc(Expr *Fn) {
+ TypeLoc Target;
+ if (const auto *T = Fn->getType().getTypePtr()->getAs<TypedefType>()) {
+ Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc();
+
+ } else if (const auto *DR = dyn_cast<DeclRefExpr>(Fn)) {
+ const auto *D = DR->getDecl();
+ if (const auto *const VD = dyn_cast<VarDecl>(D)) {
+ Target = VD->getTypeSourceInfo()->getTypeLoc();
+ }
+ }
+
+ if (!Target)
+ return {};
+
+ if (auto P = Target.getAs<PointerTypeLoc>()) {
+ Target = P.getPointeeLoc();
+ }
+
+ if (auto P = Target.getAs<ParenTypeLoc>()) {
+ Target = P.getInnerLoc();
+ }
+
+ if (auto F = Target.getAs<FunctionProtoTypeLoc>()) {
+ return F;
+ }
+
+ return {};
+}
+
QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
SourceLocation OpenParLoc) {
Fn = unwrapParenList(Fn);
@@ -6079,6 +6114,8 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
} else {
// Lastly we check whether expression's type is function pointer or
// function.
+
+ FunctionProtoTypeLoc P = GetPrototypeLoc(NakedFn);
QualType T = NakedFn->getType();
if (!T->getPointeeType().isNull())
T = T->getPointeeType();
@@ -6087,8 +6124,13 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
if (!TooManyArguments(FP->getNumParams(),
ArgsWithoutDependentTypes.size(),
/*PartialOverloading=*/true) ||
- FP->isVariadic())
- Results.push_back(ResultCandidate(FP));
+ FP->isVariadic()) {
+ if (P) {
+ Results.push_back(ResultCandidate(P));
+ } else {
+ Results.push_back(ResultCandidate(FP));
+ }
+ }
} else if (auto FT = T->getAs<FunctionType>())
// No prototype and declaration, it may be a K & R style function.
Results.push_back(ResultCandidate(FT));
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
index 5a546503cced..8d2fc5331a0d 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaDecl.cpp
@@ -9411,15 +9411,27 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD->setLocalExternDecl();
if (getLangOpts().CPlusPlus) {
+ // The rules for implicit inlines changed in C++20 for methods and friends
+ // with an in-class definition (when such a definition is not attached to
+ // the global module). User-specified 'inline' overrides this (set when
+ // the function decl is created above).
+ // FIXME: We need a better way to separate C++ standard and clang modules.
+ bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlusModules ||
+ !NewFD->getOwningModule() ||
+ NewFD->getOwningModule()->isGlobalModule() ||
+ NewFD->getOwningModule()->isModuleMapModule();
bool isInline = D.getDeclSpec().isInlineSpecified();
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier();
isFriend = D.getDeclSpec().isFriendSpecified();
if (isFriend && !isInline && D.isFunctionDefinition()) {
- // C++ [class.friend]p5
+ // Pre-C++20 [class.friend]p5
// A function can be defined in a friend declaration of a
// class . . . . Such a function is implicitly inline.
- NewFD->setImplicitlyInline();
+ // Post C++20 [class.friend]p7
+ // Such a function is implicitly an inline function if it is attached
+ // to the global module.
+ NewFD->setImplicitlyInline(ImplicitInlineCXX20);
}
// If this is a method defined in an __interface, and is not a constructor
@@ -9702,11 +9714,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
if (isa<CXXMethodDecl>(NewFD) && DC == CurContext &&
- D.isFunctionDefinition()) {
- // C++ [class.mfct]p2:
+ D.isFunctionDefinition() && !isInline) {
+ // Pre C++20 [class.mfct]p2:
// A member function may be defined (8.4) in its class definition, in
// which case it is an inline member function (7.1.2)
- NewFD->setImplicitlyInline();
+ // Post C++20 [class.mfct]p1:
+ // If a member function is attached to the global module and is defined
+ // in its class definition, it is inline.
+ NewFD->setImplicitlyInline(ImplicitInlineCXX20);
}
if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
@@ -16194,7 +16209,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
ED->setIntegerTypeSourceInfo(TI);
else
ED->setIntegerType(QualType(EnumUnderlying.get<const Type *>(), 0));
- ED->setPromotionType(ED->getIntegerType());
+ QualType EnumTy = ED->getIntegerType();
+ ED->setPromotionType(EnumTy->isPromotableIntegerType()
+ ? Context.getPromotedIntegerType(EnumTy)
+ : EnumTy);
}
} else { // struct/union
New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name,
@@ -16816,8 +16834,11 @@ CreateNewDecl:
if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>())
ED->setIntegerTypeSourceInfo(TI);
else
- ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0));
- ED->setPromotionType(ED->getIntegerType());
+ ED->setIntegerType(QualType(EnumUnderlying.get<const Type *>(), 0));
+ QualType EnumTy = ED->getIntegerType();
+ ED->setPromotionType(EnumTy->isPromotableIntegerType()
+ ? Context.getPromotedIntegerType(EnumTy)
+ : EnumTy);
assert(ED->isComplete() && "enum with type should be complete");
}
} else {
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp
index 742c4828b8dc..cd5cdbde7f3f 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp
@@ -12323,7 +12323,7 @@ static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
return S.InvalidOperands(Loc, LHS, RHS);
// Check for comparisons of floating point operands using != and ==.
- if (Type->hasFloatingRepresentation() && BinaryOperator::isEqualityOp(Opc))
+ if (Type->hasFloatingRepresentation())
S.CheckFloatComparison(Loc, LHS.get(), RHS.get(), Opc);
// The result of comparisons is 'bool' in C++, 'int' in C.
@@ -12933,8 +12933,7 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);
// Check for comparisons of floating point operands using != and ==.
- if (BinaryOperator::isEqualityOp(Opc) &&
- LHSType->hasFloatingRepresentation()) {
+ if (LHSType->hasFloatingRepresentation()) {
assert(RHS.get()->getType()->hasFloatingRepresentation());
CheckFloatComparison(Loc, LHS.get(), RHS.get(), Opc);
}
@@ -12968,8 +12967,7 @@ QualType Sema::CheckSizelessVectorCompareOperands(ExprResult &LHS,
diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);
// Check for comparisons of floating point operands using != and ==.
- if (BinaryOperator::isEqualityOp(Opc) &&
- LHSType->hasFloatingRepresentation()) {
+ if (LHSType->hasFloatingRepresentation()) {
assert(RHS.get()->getType()->hasFloatingRepresentation());
CheckFloatComparison(Loc, LHS.get(), RHS.get(), Opc);
}
@@ -15402,7 +15400,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
pty->getKind() == BuiltinType::Overload)) {
auto *OE = dyn_cast<OverloadExpr>(LHSExpr);
if (OE && !OE->hasTemplateKeyword() && !OE->hasExplicitTemplateArgs() &&
- std::any_of(OE->decls_begin(), OE->decls_end(), [](NamedDecl *ND) {
+ llvm::any_of(OE->decls(), [](NamedDecl *ND) {
return isa<FunctionTemplateDecl>(ND);
})) {
Diag(OE->getQualifier() ? OE->getQualifierLoc().getBeginLoc()
@@ -19723,7 +19721,6 @@ public:
void VisitConstantExpr(ConstantExpr *E) {
// Don't mark declarations within a ConstantExpression, as this expression
// will be evaluated and folded to a value.
- return;
}
void VisitDeclRefExpr(DeclRefExpr *E) {
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp
index 11f33c7c6363..5331193de863 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp
@@ -9006,14 +9006,14 @@ Sema::BuildExprRequirement(
cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint()
->getImmediatelyDeclaredConstraint();
ExprResult Constraint = SubstExpr(IDC, MLTAL);
- assert(!Constraint.isInvalid() &&
- "Substitution cannot fail as it is simply putting a type template "
- "argument into a concept specialization expression's parameter.");
-
- SubstitutedConstraintExpr =
- cast<ConceptSpecializationExpr>(Constraint.get());
- if (!SubstitutedConstraintExpr->isSatisfied())
- Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
+ if (Constraint.isInvalid()) {
+ Status = concepts::ExprRequirement::SS_ExprSubstitutionFailure;
+ } else {
+ SubstitutedConstraintExpr =
+ cast<ConceptSpecializationExpr>(Constraint.get());
+ if (!SubstitutedConstraintExpr->isSatisfied())
+ Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied;
+ }
}
return new (Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc,
ReturnTypeRequirement, Status,
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp
index 47c7a61f8072..242e1f81d75c 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaLookup.cpp
@@ -1615,7 +1615,10 @@ hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D,
if (!D->hasDefaultArgument())
return false;
- while (D) {
+ llvm::SmallDenseSet<const ParmDecl *, 4> Visited;
+ while (D && !Visited.count(D)) {
+ Visited.insert(D);
+
auto &DefaultArg = D->getDefaultArgStorage();
if (!DefaultArg.isInherited() && S.isAcceptable(D, Kind))
return true;
@@ -1625,7 +1628,8 @@ hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D,
Modules->push_back(S.getOwningModule(NonConstD));
}
- // If there was a previous default argument, maybe its parameter is visible.
+ // If there was a previous default argument, maybe its parameter is
+ // acceptable.
D = DefaultArg.getInheritedFrom();
}
return false;
@@ -2087,6 +2091,13 @@ bool LookupResult::isAvailableForLookup(Sema &SemaRef, NamedDecl *ND) {
if (isVisible(SemaRef, ND))
return true;
+ // Deduction guide lives in namespace scope generally, but it is just a
+ // hint to the compilers. What we actually lookup for is the generated member
+ // of the corresponding template. So it is sufficient to check the
+ // reachability of the template decl.
+ if (auto *DeductionGuide = ND->getDeclName().getCXXDeductionGuideTemplate())
+ return SemaRef.hasReachableDefinition(DeductionGuide);
+
auto *DC = ND->getDeclContext();
// If ND is not visible and it is at namespace scope, it shouldn't be found
// by name lookup.
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp b/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp
index e9a1ac17ce86..f5c24bd10daa 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaModule.cpp
@@ -344,6 +344,16 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
// statements, so imports are allowed.
ImportState = ModuleImportState::ImportAllowed;
+ // For an implementation, We already made an implicit import (its interface).
+ // Make and return the import decl to be added to the current TU.
+ if (MDK == ModuleDeclKind::Implementation) {
+ // Make the import decl for the interface.
+ ImportDecl *Import =
+ ImportDecl::Create(Context, CurContext, ModuleLoc, Mod, Path[0].second);
+ // and return it to be added.
+ return ConvertDeclToDeclGroup(Import);
+ }
+
// FIXME: Create a ModuleDecl.
return nullptr;
}
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp
index 67cf8f0371c5..95c83ebfaeab 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplate.cpp
@@ -2520,7 +2520,7 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
continue;
// Cannot make a deduction guide when unparsed arguments are present.
- if (std::any_of(CD->param_begin(), CD->param_end(), [](ParmVarDecl *P) {
+ if (llvm::any_of(CD->parameters(), [](ParmVarDecl *P) {
return !P || P->hasUnparsedDefaultArg();
}))
continue;
@@ -4573,7 +4573,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
void *InsertPos = nullptr;
if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(
Converted, InsertPos)) {
- checkSpecializationVisibility(TemplateNameLoc, Spec);
+ checkSpecializationReachability(TemplateNameLoc, Spec);
// If we already have a variable template specialization, return it.
return Spec;
}
@@ -4694,7 +4694,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
dyn_cast<VarTemplatePartialSpecializationDecl>(InstantiationPattern))
Decl->setInstantiationOf(D, InstantiationArgs);
- checkSpecializationVisibility(TemplateNameLoc, Decl);
+ checkSpecializationReachability(TemplateNameLoc, Decl);
assert(Decl && "No variable template specialization?");
return Decl;
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index bd166ff6f594..9bf6ca1f8084 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2182,6 +2182,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
// definition. We don't want non-template functions to be marked as being
// template instantiations.
Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
+ } else if (!isFriend) {
+ // If this is not a function template, and this is not a friend (that is,
+ // this is a locally declared function), save the instantiation relationship
+ // for the purposes of constraint instantiation.
+ Function->setInstantiatedFromDecl(D);
}
if (isFriend) {
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaType.cpp b/contrib/llvm-project/clang/lib/Sema/SemaType.cpp
index 3edce941c381..3ab5d26a9a75 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaType.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaType.cpp
@@ -8669,12 +8669,13 @@ bool Sema::hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
// of it will do.
*Suggested = nullptr;
for (auto *Redecl : ED->redecls()) {
- if (isVisible(Redecl))
+ if (isAcceptable(Redecl, Kind))
return true;
if (Redecl->isThisDeclarationADefinition() ||
(Redecl->isCanonicalDecl() && !*Suggested))
*Suggested = Redecl;
}
+
return false;
}
D = ED->getDefinition();
diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp
index 04ade0a3b9d0..76281d26b2ae 100644
--- a/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp
+++ b/contrib/llvm-project/clang/lib/Serialization/ASTReader.cpp
@@ -9445,6 +9445,31 @@ void ASTReader::finishPendingActions() {
PendingMergedDefinitionsToDeduplicate.clear();
}
+static unsigned computeODRHash(QualType Ty) {
+ ODRHash Hasher;
+ Hasher.AddQualType(Ty);
+ return Hasher.CalculateHash();
+}
+
+static unsigned computeODRHash(const Stmt *S) {
+ ODRHash Hasher;
+ Hasher.AddStmt(S);
+ return Hasher.CalculateHash();
+}
+
+static unsigned computeODRHash(const Decl *D) {
+ assert(D);
+ ODRHash Hasher;
+ Hasher.AddSubDecl(D);
+ return Hasher.CalculateHash();
+}
+
+static unsigned computeODRHash(const TemplateArgument &TA) {
+ ODRHash Hasher;
+ Hasher.AddTemplateArgument(TA);
+ return Hasher.CalculateHash();
+}
+
void ASTReader::diagnoseOdrViolations() {
if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() &&
PendingFunctionOdrMergeFailures.empty() &&
@@ -9584,42 +9609,6 @@ void ASTReader::diagnoseOdrViolations() {
// we're producing our diagnostics.
Deserializing RecursionGuard(this);
- // Common code for hashing helpers.
- ODRHash Hash;
- auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
- Hash.clear();
- Hash.AddQualType(Ty);
- return Hash.CalculateHash();
- };
-
- auto ComputeODRHash = [&Hash](const Stmt *S) {
- assert(S);
- Hash.clear();
- Hash.AddStmt(S);
- return Hash.CalculateHash();
- };
-
- auto ComputeSubDeclODRHash = [&Hash](const Decl *D) {
- assert(D);
- Hash.clear();
- Hash.AddSubDecl(D);
- return Hash.CalculateHash();
- };
-
- auto ComputeTemplateArgumentODRHash = [&Hash](const TemplateArgument &TA) {
- Hash.clear();
- Hash.AddTemplateArgument(TA);
- return Hash.CalculateHash();
- };
-
- auto ComputeTemplateParameterListODRHash =
- [&Hash](const TemplateParameterList *TPL) {
- assert(TPL);
- Hash.clear();
- Hash.AddTemplateParameterList(TPL);
- return Hash.CalculateHash();
- };
-
// Used with err_module_odr_violation_mismatch_decl and
// note_module_odr_violation_mismatch_decl
// This list should be the same Decl's as in ODRHash::isDeclToBeProcessed
@@ -9639,49 +9628,13 @@ void ASTReader::diagnoseOdrViolations() {
Other
};
- // Used with err_module_odr_violation_record and
- // note_module_odr_violation_record
- enum ODRCXXRecordDifference {
- StaticAssertCondition,
- StaticAssertMessage,
- StaticAssertOnlyMessage,
- MethodName,
- MethodDeleted,
- MethodDefaulted,
- MethodVirtual,
- MethodStatic,
- MethodVolatile,
- MethodConst,
- MethodInline,
- MethodNumberParameters,
- MethodParameterType,
- MethodParameterName,
- MethodParameterSingleDefaultArgument,
- MethodParameterDifferentDefaultArgument,
- MethodNoTemplateArguments,
- MethodDifferentNumberTemplateArguments,
- MethodDifferentTemplateArgument,
- MethodSingleBody,
- MethodDifferentBody,
- FriendTypeFunction,
- FriendType,
- FriendFunction,
- FunctionTemplateDifferentNumberParameters,
- FunctionTemplateParameterDifferentKind,
- FunctionTemplateParameterName,
- FunctionTemplateParameterSingleDefaultArgument,
- FunctionTemplateParameterDifferentDefaultArgument,
- FunctionTemplateParameterDifferentType,
- FunctionTemplatePackParameter,
- };
-
// These lambdas have the common portions of the ODR diagnostics. This
// has the same return as Diag(), so addition parameters can be passed
// in with operator<<
- auto ODRDiagField = [this, &ComputeQualTypeODRHash, &ComputeODRHash](
- NamedDecl *FirstRecord, StringRef FirstModule,
- StringRef SecondModule, FieldDecl *FirstField,
- FieldDecl *SecondField) {
+ auto ODRDiagField = [this](NamedDecl *FirstRecord, StringRef FirstModule,
+ StringRef SecondModule,
+ const FieldDecl *FirstField,
+ const FieldDecl *SecondField) {
enum ODRFieldDifference {
FieldName,
FieldTypeName,
@@ -9719,8 +9672,7 @@ void ASTReader::diagnoseOdrViolations() {
QualType FirstType = FirstField->getType();
QualType SecondType = SecondField->getType();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
+ if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
DiagError(FieldTypeName) << FirstII << FirstType;
DiagNote(FieldTypeName) << SecondII << SecondType;
return true;
@@ -9735,10 +9687,8 @@ void ASTReader::diagnoseOdrViolations() {
}
if (IsFirstBitField && IsSecondBitField) {
- unsigned FirstBitWidthHash =
- ComputeODRHash(FirstField->getBitWidth());
- unsigned SecondBitWidthHash =
- ComputeODRHash(SecondField->getBitWidth());
+ unsigned FirstBitWidthHash = computeODRHash(FirstField->getBitWidth());
+ unsigned SecondBitWidthHash = computeODRHash(SecondField->getBitWidth());
if (FirstBitWidthHash != SecondBitWidthHash) {
DiagError(FieldDifferentWidthBitField)
<< FirstII << FirstField->getBitWidth()->getSourceRange();
@@ -9771,8 +9721,8 @@ void ASTReader::diagnoseOdrViolations() {
}
if (FirstInitializer && SecondInitializer) {
- unsigned FirstInitHash = ComputeODRHash(FirstInitializer);
- unsigned SecondInitHash = ComputeODRHash(SecondInitializer);
+ unsigned FirstInitHash = computeODRHash(FirstInitializer);
+ unsigned SecondInitHash = computeODRHash(SecondInitializer);
if (FirstInitHash != SecondInitHash) {
DiagError(FieldDifferentInitializers)
<< FirstII << FirstInitializer->getSourceRange();
@@ -9786,10 +9736,9 @@ void ASTReader::diagnoseOdrViolations() {
};
auto ODRDiagTypeDefOrAlias =
- [this, &ComputeQualTypeODRHash](
- NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,
- TypedefNameDecl *FirstTD, TypedefNameDecl *SecondTD,
- bool IsTypeAlias) {
+ [this](NamedDecl *FirstRecord, StringRef FirstModule,
+ StringRef SecondModule, const TypedefNameDecl *FirstTD,
+ const TypedefNameDecl *SecondTD, bool IsTypeAlias) {
enum ODRTypedefDifference {
TypedefName,
TypedefType,
@@ -9809,8 +9758,8 @@ void ASTReader::diagnoseOdrViolations() {
<< SecondModule << SecondTD->getSourceRange() << DiffType;
};
- auto FirstName = FirstTD->getDeclName();
- auto SecondName = SecondTD->getDeclName();
+ DeclarationName FirstName = FirstTD->getDeclName();
+ DeclarationName SecondName = SecondTD->getDeclName();
if (FirstName != SecondName) {
DiagError(TypedefName) << IsTypeAlias << FirstName;
DiagNote(TypedefName) << IsTypeAlias << SecondName;
@@ -9819,8 +9768,7 @@ void ASTReader::diagnoseOdrViolations() {
QualType FirstType = FirstTD->getUnderlyingType();
QualType SecondType = SecondTD->getUnderlyingType();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
+ if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
DiagError(TypedefType) << IsTypeAlias << FirstName << FirstType;
DiagNote(TypedefType) << IsTypeAlias << SecondName << SecondType;
return true;
@@ -9829,10 +9777,9 @@ void ASTReader::diagnoseOdrViolations() {
return false;
};
- auto ODRDiagVar = [&ComputeQualTypeODRHash, &ComputeODRHash,
- this](NamedDecl *FirstRecord, StringRef FirstModule,
- StringRef SecondModule, VarDecl *FirstVD,
- VarDecl *SecondVD) {
+ auto ODRDiagVar = [this](NamedDecl *FirstRecord, StringRef FirstModule,
+ StringRef SecondModule, const VarDecl *FirstVD,
+ const VarDecl *SecondVD) {
enum ODRVarDifference {
VarName,
VarType,
@@ -9854,8 +9801,8 @@ void ASTReader::diagnoseOdrViolations() {
<< SecondModule << SecondVD->getSourceRange() << DiffType;
};
- auto FirstName = FirstVD->getDeclName();
- auto SecondName = SecondVD->getDeclName();
+ DeclarationName FirstName = FirstVD->getDeclName();
+ DeclarationName SecondName = SecondVD->getDeclName();
if (FirstName != SecondName) {
DiagError(VarName) << FirstName;
DiagNote(VarName) << SecondName;
@@ -9864,8 +9811,7 @@ void ASTReader::diagnoseOdrViolations() {
QualType FirstType = FirstVD->getType();
QualType SecondType = SecondVD->getType();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
+ if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
DiagError(VarType) << FirstName << FirstType;
DiagNote(VarType) << SecondName << SecondType;
return true;
@@ -9887,7 +9833,7 @@ void ASTReader::diagnoseOdrViolations() {
}
if (FirstInit && SecondInit &&
- ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
+ computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
DiagError(VarDifferentInitializer)
<< FirstName << FirstInit->getSourceRange();
DiagNote(VarDifferentInitializer)
@@ -9905,52 +9851,13 @@ void ASTReader::diagnoseOdrViolations() {
return false;
};
- auto DifferenceSelector = [](Decl *D) {
- assert(D && "valid Decl required");
- switch (D->getKind()) {
- default:
- return Other;
- case Decl::AccessSpec:
- switch (D->getAccess()) {
- case AS_public:
- return PublicSpecifer;
- case AS_private:
- return PrivateSpecifer;
- case AS_protected:
- return ProtectedSpecifer;
- case AS_none:
- break;
- }
- llvm_unreachable("Invalid access specifier");
- case Decl::StaticAssert:
- return StaticAssert;
- case Decl::Field:
- return Field;
- case Decl::CXXMethod:
- case Decl::CXXConstructor:
- case Decl::CXXDestructor:
- return CXXMethod;
- case Decl::TypeAlias:
- return TypeAlias;
- case Decl::Typedef:
- return TypeDef;
- case Decl::Var:
- return Var;
- case Decl::Friend:
- return Friend;
- case Decl::FunctionTemplate:
- return FunctionTemplate;
- }
- };
-
using DeclHashes = llvm::SmallVector<std::pair<Decl *, unsigned>, 4>;
- auto PopulateHashes = [&ComputeSubDeclODRHash](DeclHashes &Hashes,
- RecordDecl *Record,
- const DeclContext *DC) {
+ auto PopulateHashes = [](DeclHashes &Hashes, RecordDecl *Record,
+ const DeclContext *DC) {
for (auto *D : Record->decls()) {
if (!ODRHash::isDeclToBeProcessed(D, DC))
continue;
- Hashes.emplace_back(D, ComputeSubDeclODRHash(D));
+ Hashes.emplace_back(D, computeODRHash(D));
}
};
@@ -9962,8 +9869,45 @@ void ASTReader::diagnoseOdrViolations() {
// If there is a diagnoseable difference, FirstDiffType and
// SecondDiffType will not be Other and FirstDecl and SecondDecl will be
// filled in if not EndOfClass.
- auto FindTypeDiffs = [&DifferenceSelector](DeclHashes &FirstHashes,
- DeclHashes &SecondHashes) {
+ auto FindTypeDiffs = [](DeclHashes &FirstHashes, DeclHashes &SecondHashes) {
+ auto DifferenceSelector = [](Decl *D) {
+ assert(D && "valid Decl required");
+ switch (D->getKind()) {
+ default:
+ return Other;
+ case Decl::AccessSpec:
+ switch (D->getAccess()) {
+ case AS_public:
+ return PublicSpecifer;
+ case AS_private:
+ return PrivateSpecifer;
+ case AS_protected:
+ return ProtectedSpecifer;
+ case AS_none:
+ break;
+ }
+ llvm_unreachable("Invalid access specifier");
+ case Decl::StaticAssert:
+ return StaticAssert;
+ case Decl::Field:
+ return Field;
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ return CXXMethod;
+ case Decl::TypeAlias:
+ return TypeAlias;
+ case Decl::Typedef:
+ return TypeDef;
+ case Decl::Var:
+ return Var;
+ case Decl::Friend:
+ return Friend;
+ case Decl::FunctionTemplate:
+ return FunctionTemplate;
+ }
+ };
+
DiffResult DR;
auto FirstIt = FirstHashes.begin();
auto SecondIt = SecondHashes.begin();
@@ -10062,19 +10006,6 @@ void ASTReader::diagnoseOdrViolations() {
continue;
std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);
- auto ODRDiagDeclError = [FirstRecord, &FirstModule,
- this](SourceLocation Loc, SourceRange Range,
- ODRCXXRecordDifference DiffType) {
- return Diag(Loc, diag::err_module_odr_violation_record)
- << FirstRecord << FirstModule.empty() << FirstModule << Range
- << DiffType;
- };
- auto ODRDiagDeclNote = [&SecondModule,
- this](SourceLocation Loc, SourceRange Range,
- ODRCXXRecordDifference DiffType) {
- return Diag(Loc, diag::note_module_odr_violation_record)
- << SecondModule << Range << DiffType;
- };
auto *FirstDD = FirstRecord->DefinitionData;
auto *SecondDD = RecordPair.second;
@@ -10103,20 +10034,18 @@ void ASTReader::diagnoseOdrViolations() {
return Diag(Loc, diag::note_module_odr_violation_definition_data)
<< SecondModule << Range << DiffType;
};
-
- unsigned FirstNumBases = FirstDD->NumBases;
- unsigned FirstNumVBases = FirstDD->NumVBases;
- unsigned SecondNumBases = SecondDD->NumBases;
- unsigned SecondNumVBases = SecondDD->NumVBases;
-
auto GetSourceRange = [](struct CXXRecordDecl::DefinitionData *DD) {
unsigned NumBases = DD->NumBases;
if (NumBases == 0) return SourceRange();
- auto bases = DD->bases();
+ ArrayRef<CXXBaseSpecifier> bases = DD->bases();
return SourceRange(bases[0].getBeginLoc(),
bases[NumBases - 1].getEndLoc());
};
+ unsigned FirstNumBases = FirstDD->NumBases;
+ unsigned FirstNumVBases = FirstDD->NumVBases;
+ unsigned SecondNumBases = SecondDD->NumBases;
+ unsigned SecondNumVBases = SecondDD->NumVBases;
if (FirstNumBases != SecondNumBases) {
ODRDiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
NumBases)
@@ -10139,30 +10068,30 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
- auto FirstBases = FirstDD->bases();
- auto SecondBases = SecondDD->bases();
- unsigned i = 0;
- for (i = 0; i < FirstNumBases; ++i) {
- auto FirstBase = FirstBases[i];
- auto SecondBase = SecondBases[i];
- if (ComputeQualTypeODRHash(FirstBase.getType()) !=
- ComputeQualTypeODRHash(SecondBase.getType())) {
+ ArrayRef<CXXBaseSpecifier> FirstBases = FirstDD->bases();
+ ArrayRef<CXXBaseSpecifier> SecondBases = SecondDD->bases();
+ unsigned I = 0;
+ for (I = 0; I < FirstNumBases; ++I) {
+ const CXXBaseSpecifier FirstBase = FirstBases[I];
+ const CXXBaseSpecifier SecondBase = SecondBases[I];
+ if (computeODRHash(FirstBase.getType()) !=
+ computeODRHash(SecondBase.getType())) {
ODRDiagBaseError(FirstRecord->getLocation(),
FirstBase.getSourceRange(), BaseType)
- << (i + 1) << FirstBase.getType();
+ << (I + 1) << FirstBase.getType();
ODRDiagBaseNote(SecondRecord->getLocation(),
SecondBase.getSourceRange(), BaseType)
- << (i + 1) << SecondBase.getType();
+ << (I + 1) << SecondBase.getType();
break;
}
if (FirstBase.isVirtual() != SecondBase.isVirtual()) {
ODRDiagBaseError(FirstRecord->getLocation(),
FirstBase.getSourceRange(), BaseVirtual)
- << (i + 1) << FirstBase.isVirtual() << FirstBase.getType();
+ << (I + 1) << FirstBase.isVirtual() << FirstBase.getType();
ODRDiagBaseNote(SecondRecord->getLocation(),
SecondBase.getSourceRange(), BaseVirtual)
- << (i + 1) << SecondBase.isVirtual() << SecondBase.getType();
+ << (I + 1) << SecondBase.isVirtual() << SecondBase.getType();
break;
}
@@ -10170,17 +10099,17 @@ void ASTReader::diagnoseOdrViolations() {
SecondBase.getAccessSpecifierAsWritten()) {
ODRDiagBaseError(FirstRecord->getLocation(),
FirstBase.getSourceRange(), BaseAccess)
- << (i + 1) << FirstBase.getType()
+ << (I + 1) << FirstBase.getType()
<< (int)FirstBase.getAccessSpecifierAsWritten();
ODRDiagBaseNote(SecondRecord->getLocation(),
SecondBase.getSourceRange(), BaseAccess)
- << (i + 1) << SecondBase.getType()
+ << (I + 1) << SecondBase.getType()
<< (int)SecondBase.getAccessSpecifierAsWritten();
break;
}
}
- if (i != FirstNumBases) {
+ if (I != FirstNumBases) {
Diagnosed = true;
break;
}
@@ -10198,13 +10127,12 @@ void ASTReader::diagnoseOdrViolations() {
DeclHashes FirstTemplateHashes;
DeclHashes SecondTemplateHashes;
- auto PopulateTemplateParameterHashs =
- [&ComputeSubDeclODRHash](DeclHashes &Hashes,
- const ClassTemplateDecl *TD) {
- for (auto *D : TD->getTemplateParameters()->asArray()) {
- Hashes.emplace_back(D, ComputeSubDeclODRHash(D));
- }
- };
+ auto PopulateTemplateParameterHashs = [](DeclHashes &Hashes,
+ const ClassTemplateDecl *TD) {
+ for (auto *D : TD->getTemplateParameters()->asArray()) {
+ Hashes.emplace_back(D, computeODRHash(D));
+ }
+ };
PopulateTemplateParameterHashs(FirstTemplateHashes, FirstTemplate);
PopulateTemplateParameterHashs(SecondTemplateHashes, SecondTemplate);
@@ -10288,11 +10216,11 @@ void ASTReader::diagnoseOdrViolations() {
PopulateHashes(FirstHashes, FirstRecord, DC);
PopulateHashes(SecondHashes, SecondRecord, DC);
- auto DR = FindTypeDiffs(FirstHashes, SecondHashes);
+ DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
- Decl *FirstDecl = DR.FirstDecl;
- Decl *SecondDecl = DR.SecondDecl;
+ const Decl *FirstDecl = DR.FirstDecl;
+ const Decl *SecondDecl = DR.SecondDecl;
if (FirstDiffType == Other || SecondDiffType == Other) {
DiagnoseODRUnexpected(DR, FirstRecord, FirstModule, SecondRecord,
@@ -10308,8 +10236,56 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
- assert(FirstDiffType == SecondDiffType);
+ // Used with err_module_odr_violation_record and
+ // note_module_odr_violation_record
+ enum ODRCXXRecordDifference {
+ StaticAssertCondition,
+ StaticAssertMessage,
+ StaticAssertOnlyMessage,
+ MethodName,
+ MethodDeleted,
+ MethodDefaulted,
+ MethodVirtual,
+ MethodStatic,
+ MethodVolatile,
+ MethodConst,
+ MethodInline,
+ MethodNumberParameters,
+ MethodParameterType,
+ MethodParameterName,
+ MethodParameterSingleDefaultArgument,
+ MethodParameterDifferentDefaultArgument,
+ MethodNoTemplateArguments,
+ MethodDifferentNumberTemplateArguments,
+ MethodDifferentTemplateArgument,
+ MethodSingleBody,
+ MethodDifferentBody,
+ FriendTypeFunction,
+ FriendType,
+ FriendFunction,
+ FunctionTemplateDifferentNumberParameters,
+ FunctionTemplateParameterDifferentKind,
+ FunctionTemplateParameterName,
+ FunctionTemplateParameterSingleDefaultArgument,
+ FunctionTemplateParameterDifferentDefaultArgument,
+ FunctionTemplateParameterDifferentType,
+ FunctionTemplatePackParameter,
+ };
+ auto ODRDiagDeclError = [FirstRecord, &FirstModule,
+ this](SourceLocation Loc, SourceRange Range,
+ ODRCXXRecordDifference DiffType) {
+ return Diag(Loc, diag::err_module_odr_violation_record)
+ << FirstRecord << FirstModule.empty() << FirstModule << Range
+ << DiffType;
+ };
+ auto ODRDiagDeclNote = [&SecondModule,
+ this](SourceLocation Loc, SourceRange Range,
+ ODRCXXRecordDifference DiffType) {
+ return Diag(Loc, diag::note_module_odr_violation_record)
+ << SecondModule << Range << DiffType;
+ };
+ assert(FirstDiffType == SecondDiffType);
switch (FirstDiffType) {
case Other:
case EndOfClass:
@@ -10319,13 +10295,13 @@ void ASTReader::diagnoseOdrViolations() {
llvm_unreachable("Invalid diff type");
case StaticAssert: {
- StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl);
- StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl);
+ const StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl);
+ const StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl);
- Expr *FirstExpr = FirstSA->getAssertExpr();
- Expr *SecondExpr = SecondSA->getAssertExpr();
- unsigned FirstODRHash = ComputeODRHash(FirstExpr);
- unsigned SecondODRHash = ComputeODRHash(SecondExpr);
+ const Expr *FirstExpr = FirstSA->getAssertExpr();
+ const Expr *SecondExpr = SecondSA->getAssertExpr();
+ unsigned FirstODRHash = computeODRHash(FirstExpr);
+ unsigned SecondODRHash = computeODRHash(SecondExpr);
if (FirstODRHash != SecondODRHash) {
ODRDiagDeclError(FirstExpr->getBeginLoc(),
FirstExpr->getSourceRange(), StaticAssertCondition);
@@ -10335,8 +10311,8 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
- StringLiteral *FirstStr = FirstSA->getMessage();
- StringLiteral *SecondStr = SecondSA->getMessage();
+ const StringLiteral *FirstStr = FirstSA->getMessage();
+ const StringLiteral *SecondStr = SecondSA->getMessage();
assert((FirstStr || SecondStr) && "Both messages cannot be empty");
if ((FirstStr && !SecondStr) || (!FirstStr && SecondStr)) {
SourceLocation FirstLoc, SecondLoc;
@@ -10451,8 +10427,8 @@ void ASTReader::diagnoseOdrViolations() {
// CXXMethodDecl::isStatic uses the canonical Decl. With Decl merging,
// FirstDecl is the canonical Decl of SecondDecl, so the storage
// class needs to be checked instead.
- const auto FirstStorage = FirstMethod->getStorageClass();
- const auto SecondStorage = SecondMethod->getStorageClass();
+ StorageClass FirstStorage = FirstMethod->getStorageClass();
+ StorageClass SecondStorage = SecondMethod->getStorageClass();
const bool FirstStatic = FirstStorage == SC_Static;
const bool SecondStatic = SecondStorage == SC_Static;
if (FirstStatic != SecondStatic) {
@@ -10507,8 +10483,8 @@ void ASTReader::diagnoseOdrViolations() {
QualType FirstParamType = FirstParam->getType();
QualType SecondParamType = SecondParam->getType();
if (FirstParamType != SecondParamType &&
- ComputeQualTypeODRHash(FirstParamType) !=
- ComputeQualTypeODRHash(SecondParamType)) {
+ computeODRHash(FirstParamType) !=
+ computeODRHash(SecondParamType)) {
if (const DecayedType *ParamDecayedType =
FirstParamType->getAs<DecayedType>()) {
DiagMethodError(MethodParameterType)
@@ -10555,14 +10531,13 @@ void ASTReader::diagnoseOdrViolations() {
}
if (FirstInit && SecondInit &&
- ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
+ computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
DiagMethodError(MethodParameterDifferentDefaultArgument)
<< (I + 1) << FirstInit->getSourceRange();
DiagMethodNote(MethodParameterDifferentDefaultArgument)
<< (I + 1) << SecondInit->getSourceRange();
ParameterMismatch = true;
break;
-
}
}
@@ -10571,9 +10546,9 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
- const auto *FirstTemplateArgs =
+ const TemplateArgumentList *FirstTemplateArgs =
FirstMethod->getTemplateSpecializationArgs();
- const auto *SecondTemplateArgs =
+ const TemplateArgumentList *SecondTemplateArgs =
SecondMethod->getTemplateSpecializationArgs();
if ((FirstTemplateArgs && !SecondTemplateArgs) ||
@@ -10619,8 +10594,7 @@ void ASTReader::diagnoseOdrViolations() {
for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) {
const TemplateArgument &FirstTA = *FirstExpandedList[i],
&SecondTA = *SecondExpandedList[i];
- if (ComputeTemplateArgumentODRHash(FirstTA) ==
- ComputeTemplateArgumentODRHash(SecondTA)) {
+ if (computeODRHash(FirstTA) == computeODRHash(SecondTA)) {
continue;
}
@@ -10639,10 +10613,10 @@ void ASTReader::diagnoseOdrViolations() {
}
// Compute the hash of the method as if it has no body.
- auto ComputeCXXMethodODRHash = [&Hash](const CXXMethodDecl *D) {
- Hash.clear();
- Hash.AddFunctionDecl(D, true /*SkipBody*/);
- return Hash.CalculateHash();
+ auto ComputeCXXMethodODRHash = [](const CXXMethodDecl *D) {
+ ODRHash Hasher;
+ Hasher.AddFunctionDecl(D, true /*SkipBody*/);
+ return Hasher.CalculateHash();
};
// Compare the hash generated to the hash stored. A difference means
@@ -10684,11 +10658,11 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
case Friend: {
- FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl);
- FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl);
+ const FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl);
+ const FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl);
- NamedDecl *FirstND = FirstFriend->getFriendDecl();
- NamedDecl *SecondND = SecondFriend->getFriendDecl();
+ const NamedDecl *FirstND = FirstFriend->getFriendDecl();
+ const NamedDecl *SecondND = SecondFriend->getFriendDecl();
TypeSourceInfo *FirstTSI = FirstFriend->getFriendType();
TypeSourceInfo *SecondTSI = SecondFriend->getFriendType();
@@ -10707,8 +10681,8 @@ void ASTReader::diagnoseOdrViolations() {
if (FirstTSI && SecondTSI) {
QualType FirstFriendType = FirstTSI->getType();
QualType SecondFriendType = SecondTSI->getType();
- assert(ComputeQualTypeODRHash(FirstFriendType) !=
- ComputeQualTypeODRHash(SecondFriendType));
+ assert(computeODRHash(FirstFriendType) !=
+ computeODRHash(SecondFriendType));
ODRDiagDeclError(FirstFriend->getFriendLoc(),
FirstFriend->getSourceRange(), FriendType)
<< FirstFriendType;
@@ -10729,9 +10703,9 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
case FunctionTemplate: {
- FunctionTemplateDecl *FirstTemplate =
+ const FunctionTemplateDecl *FirstTemplate =
cast<FunctionTemplateDecl>(FirstDecl);
- FunctionTemplateDecl *SecondTemplate =
+ const FunctionTemplateDecl *SecondTemplate =
cast<FunctionTemplateDecl>(SecondDecl);
TemplateParameterList *FirstTPL =
@@ -10826,8 +10800,7 @@ void ASTReader::diagnoseOdrViolations() {
if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
QualType FirstType = FirstTTPD->getDefaultArgument();
QualType SecondType = SecondTTPD->getDefaultArgument();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
+ if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
DiagTemplateError(
FunctionTemplateParameterDifferentDefaultArgument)
<< (i + 1) << FirstType;
@@ -10862,6 +10835,14 @@ void ASTReader::diagnoseOdrViolations() {
TemplateParameterList *SecondTPL =
SecondTTPD->getTemplateParameters();
+ auto ComputeTemplateParameterListODRHash =
+ [](const TemplateParameterList *TPL) {
+ assert(TPL);
+ ODRHash Hasher;
+ Hasher.AddTemplateParameterList(TPL);
+ return Hasher.CalculateHash();
+ };
+
if (ComputeTemplateParameterListODRHash(FirstTPL) !=
ComputeTemplateParameterListODRHash(SecondTPL)) {
DiagTemplateError(FunctionTemplateParameterDifferentType)
@@ -10892,8 +10873,7 @@ void ASTReader::diagnoseOdrViolations() {
FirstTTPD->getDefaultArgument().getArgument();
TemplateArgument SecondTA =
SecondTTPD->getDefaultArgument().getArgument();
- if (ComputeTemplateArgumentODRHash(FirstTA) !=
- ComputeTemplateArgumentODRHash(SecondTA)) {
+ if (computeODRHash(FirstTA) != computeODRHash(SecondTA)) {
DiagTemplateError(
FunctionTemplateParameterDifferentDefaultArgument)
<< (i + 1) << FirstTA;
@@ -10925,8 +10905,7 @@ void ASTReader::diagnoseOdrViolations() {
QualType FirstType = FirstNTTPD->getType();
QualType SecondType = SecondNTTPD->getType();
- if (ComputeQualTypeODRHash(FirstType) !=
- ComputeQualTypeODRHash(SecondType)) {
+ if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
DiagTemplateError(FunctionTemplateParameterDifferentType)
<< (i + 1);
DiagTemplateNote(FunctionTemplateParameterDifferentType)
@@ -10953,8 +10932,8 @@ void ASTReader::diagnoseOdrViolations() {
if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
- if (ComputeODRHash(FirstDefaultArgument) !=
- ComputeODRHash(SecondDefaultArgument)) {
+ if (computeODRHash(FirstDefaultArgument) !=
+ computeODRHash(SecondDefaultArgument)) {
DiagTemplateError(
FunctionTemplateParameterDifferentDefaultArgument)
<< (i + 1) << FirstDefaultArgument;
@@ -11050,8 +11029,8 @@ void ASTReader::diagnoseOdrViolations() {
<< SecondModule << Range << DiffType;
};
- if (ComputeQualTypeODRHash(FirstFunction->getReturnType()) !=
- ComputeQualTypeODRHash(SecondFunction->getReturnType())) {
+ if (computeODRHash(FirstFunction->getReturnType()) !=
+ computeODRHash(SecondFunction->getReturnType())) {
ODRDiagError(FirstFunction->getReturnTypeSourceRange().getBegin(),
FirstFunction->getReturnTypeSourceRange(), ReturnType)
<< FirstFunction->getReturnType();
@@ -11065,11 +11044,11 @@ void ASTReader::diagnoseOdrViolations() {
assert(FirstFunction->param_size() == SecondFunction->param_size() &&
"Merged functions with different number of parameters");
- auto ParamSize = FirstFunction->param_size();
+ size_t ParamSize = FirstFunction->param_size();
bool ParameterMismatch = false;
for (unsigned I = 0; I < ParamSize; ++I) {
- auto *FirstParam = FirstFunction->getParamDecl(I);
- auto *SecondParam = SecondFunction->getParamDecl(I);
+ const ParmVarDecl *FirstParam = FirstFunction->getParamDecl(I);
+ const ParmVarDecl *SecondParam = SecondFunction->getParamDecl(I);
assert(getContext().hasSameType(FirstParam->getType(),
SecondParam->getType()) &&
@@ -11089,8 +11068,7 @@ void ASTReader::diagnoseOdrViolations() {
QualType FirstParamType = FirstParam->getType();
QualType SecondParamType = SecondParam->getType();
if (FirstParamType != SecondParamType &&
- ComputeQualTypeODRHash(FirstParamType) !=
- ComputeQualTypeODRHash(SecondParamType)) {
+ computeODRHash(FirstParamType) != computeODRHash(SecondParamType)) {
if (const DecayedType *ParamDecayedType =
FirstParamType->getAs<DecayedType>()) {
ODRDiagError(FirstParam->getLocation(),
@@ -11134,7 +11112,7 @@ void ASTReader::diagnoseOdrViolations() {
}
if (FirstInit && SecondInit &&
- ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
+ computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
ParameterDifferentDefaultArgument)
<< (I + 1) << FirstInit->getSourceRange();
@@ -11145,8 +11123,7 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
- assert(ComputeSubDeclODRHash(FirstParam) ==
- ComputeSubDeclODRHash(SecondParam) &&
+ assert(computeODRHash(FirstParam) == computeODRHash(SecondParam) &&
"Undiagnosed parameter difference.");
}
@@ -11191,16 +11168,14 @@ void ASTReader::diagnoseOdrViolations() {
using DeclHashes =
llvm::SmallVector<std::pair<EnumConstantDecl *, unsigned>, 4>;
- auto PopulateHashes = [&ComputeSubDeclODRHash, FirstEnum](
- DeclHashes &Hashes, EnumDecl *Enum) {
+ auto PopulateHashes = [FirstEnum](DeclHashes &Hashes, EnumDecl *Enum) {
for (auto *D : Enum->decls()) {
// Due to decl merging, the first EnumDecl is the parent of
// Decls in both records.
if (!ODRHash::isDeclToBeProcessed(D, FirstEnum))
continue;
assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind");
- Hashes.emplace_back(cast<EnumConstantDecl>(D),
- ComputeSubDeclODRHash(D));
+ Hashes.emplace_back(cast<EnumConstantDecl>(D), computeODRHash(D));
}
};
DeclHashes FirstHashes;
@@ -11266,8 +11241,8 @@ void ASTReader::diagnoseOdrViolations() {
}
if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) {
- if (ComputeQualTypeODRHash(FirstUnderlyingType) !=
- ComputeQualTypeODRHash(SecondUnderlyingType)) {
+ if (computeODRHash(FirstUnderlyingType) !=
+ computeODRHash(SecondUnderlyingType)) {
ODRDiagError(FirstEnum, DifferentSpecifiedTypes)
<< FirstUnderlyingType;
ODRDiagNote(SecondEnum, DifferentSpecifiedTypes)
@@ -11292,39 +11267,38 @@ void ASTReader::diagnoseOdrViolations() {
for (unsigned I = 0; I < FirstHashes.size(); ++I) {
if (FirstHashes[I].second == SecondHashes[I].second)
continue;
- const EnumConstantDecl *FirstEnumConstant = FirstHashes[I].first;
- const EnumConstantDecl *SecondEnumConstant = SecondHashes[I].first;
+ const EnumConstantDecl *FirstConstant = FirstHashes[I].first;
+ const EnumConstantDecl *SecondConstant = SecondHashes[I].first;
- if (FirstEnumConstant->getDeclName() !=
- SecondEnumConstant->getDeclName()) {
+ if (FirstConstant->getDeclName() != SecondConstant->getDeclName()) {
- ODRDiagError(FirstEnumConstant, EnumConstantName)
- << I + 1 << FirstEnumConstant;
- ODRDiagNote(SecondEnumConstant, EnumConstantName)
- << I + 1 << SecondEnumConstant;
+ ODRDiagError(FirstConstant, EnumConstantName)
+ << I + 1 << FirstConstant;
+ ODRDiagNote(SecondConstant, EnumConstantName)
+ << I + 1 << SecondConstant;
Diagnosed = true;
break;
}
- const Expr *FirstInit = FirstEnumConstant->getInitExpr();
- const Expr *SecondInit = SecondEnumConstant->getInitExpr();
+ const Expr *FirstInit = FirstConstant->getInitExpr();
+ const Expr *SecondInit = SecondConstant->getInitExpr();
if (!FirstInit && !SecondInit)
continue;
if (!FirstInit || !SecondInit) {
- ODRDiagError(FirstEnumConstant, EnumConstantSingleInitializer)
- << I + 1 << FirstEnumConstant << (FirstInit != nullptr);
- ODRDiagNote(SecondEnumConstant, EnumConstantSingleInitializer)
- << I + 1 << SecondEnumConstant << (SecondInit != nullptr);
+ ODRDiagError(FirstConstant, EnumConstantSingleInitializer)
+ << I + 1 << FirstConstant << (FirstInit != nullptr);
+ ODRDiagNote(SecondConstant, EnumConstantSingleInitializer)
+ << I + 1 << SecondConstant << (SecondInit != nullptr);
Diagnosed = true;
break;
}
- if (ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
- ODRDiagError(FirstEnumConstant, EnumConstantDifferentInitializer)
- << I + 1 << FirstEnumConstant;
- ODRDiagNote(SecondEnumConstant, EnumConstantDifferentInitializer)
- << I + 1 << SecondEnumConstant;
+ if (computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
+ ODRDiagError(FirstConstant, EnumConstantDifferentInitializer)
+ << I + 1 << FirstConstant;
+ ODRDiagNote(SecondConstant, EnumConstantDifferentInitializer)
+ << I + 1 << SecondConstant;
Diagnosed = true;
break;
}
diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
index b4506da2bb2b..d70e824224df 100644
--- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -953,6 +953,10 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
case FunctionDecl::TK_NonTemplate:
mergeRedeclarable(FD, Redecl);
break;
+ case FunctionDecl::TK_DependentNonTemplate:
+ mergeRedeclarable(FD, Redecl);
+ FD->setInstantiatedFromDecl(readDeclAs<FunctionDecl>());
+ break;
case FunctionDecl::TK_FunctionTemplate:
// Merged when we merge the template.
FD->setDescribedFunctionTemplate(readDeclAs<FunctionTemplateDecl>());
diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp
index 01f692c9611b..35b8db27bd0e 100644
--- a/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -585,6 +585,9 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
switch (D->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
break;
+ case FunctionDecl::TK_DependentNonTemplate:
+ Record.AddDeclRef(D->getInstantiatedFromDecl());
+ break;
case FunctionDecl::TK_FunctionTemplate:
Record.AddDeclRef(D->getDescribedFunctionTemplate());
break;
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 1c33648b2b32..ec1b0a70d7d3 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -40,6 +40,7 @@ class ExprInspectionChecker
void analyzerNumTimesReached(const CallExpr *CE, CheckerContext &C) const;
void analyzerCrash(const CallExpr *CE, CheckerContext &C) const;
void analyzerWarnOnDeadSymbol(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerValue(const CallExpr *CE, CheckerContext &C) const;
void analyzerDumpSValType(const CallExpr *CE, CheckerContext &C) const;
void analyzerDump(const CallExpr *CE, CheckerContext &C) const;
void analyzerExplain(const CallExpr *CE, CheckerContext &C) const;
@@ -60,6 +61,7 @@ class ExprInspectionChecker
Optional<SVal> ExprVal = None) const;
ExplodedNode *reportBug(llvm::StringRef Msg, BugReporter &BR, ExplodedNode *N,
Optional<SVal> ExprVal = None) const;
+ template <typename T> void printAndReport(CheckerContext &C, T What) const;
const Expr *getArgExpr(const CallExpr *CE, CheckerContext &C) const;
const MemRegion *getArgRegion(const CallExpr *CE, CheckerContext &C) const;
@@ -99,6 +101,7 @@ bool ExprInspectionChecker::evalCall(const CallEvent &Call,
&ExprInspectionChecker::analyzerDumpExtent)
.Case("clang_analyzer_dumpElementCount",
&ExprInspectionChecker::analyzerDumpElementCount)
+ .Case("clang_analyzer_value", &ExprInspectionChecker::analyzerValue)
.StartsWith("clang_analyzer_dumpSvalType",
&ExprInspectionChecker::analyzerDumpSValType)
.StartsWith("clang_analyzer_dump",
@@ -258,6 +261,45 @@ void ExprInspectionChecker::analyzerExplain(const CallExpr *CE,
reportBug(Ex.Visit(V), C);
}
+static void printHelper(llvm::raw_svector_ostream &Out, CheckerContext &C,
+ const llvm::APSInt &I) {
+ Out << I.getBitWidth() << (I.isUnsigned() ? "u:" : "s:");
+ Out << I;
+}
+
+static void printHelper(llvm::raw_svector_ostream &Out, CheckerContext &C,
+ SymbolRef Sym) {
+ C.getConstraintManager().printValue(Out, C.getState(), Sym);
+}
+
+static void printHelper(llvm::raw_svector_ostream &Out, CheckerContext &C,
+ SVal V) {
+ Out << V;
+}
+
+template <typename T>
+void ExprInspectionChecker::printAndReport(CheckerContext &C, T What) const {
+ llvm::SmallString<64> Str;
+ llvm::raw_svector_ostream OS(Str);
+ printHelper(OS, C, What);
+ reportBug(OS.str(), C);
+}
+
+void ExprInspectionChecker::analyzerValue(const CallExpr *CE,
+ CheckerContext &C) const {
+ const Expr *Arg = getArgExpr(CE, C);
+ if (!Arg)
+ return;
+
+ SVal V = C.getSVal(Arg);
+ if (const SymbolRef Sym = V.getAsSymbol())
+ printAndReport(C, Sym);
+ else if (const llvm::APSInt *I = V.getAsInteger())
+ printAndReport(C, *I);
+ else
+ reportBug("n/a", C);
+}
+
void ExprInspectionChecker::analyzerDumpSValType(const CallExpr *CE,
CheckerContext &C) const {
const Expr *Arg = getArgExpr(CE, C);
@@ -275,11 +317,7 @@ void ExprInspectionChecker::analyzerDump(const CallExpr *CE,
return;
SVal V = C.getSVal(Arg);
-
- llvm::SmallString<32> Str;
- llvm::raw_svector_ostream OS(Str);
- V.dumpToStream(OS);
- reportBug(OS.str(), C);
+ printAndReport(C, V);
}
void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
@@ -303,11 +341,7 @@ void ExprInspectionChecker::analyzerDumpExtent(const CallExpr *CE,
DefinedOrUnknownSVal Size =
getDynamicExtent(C.getState(), MR, C.getSValBuilder());
-
- SmallString<64> Msg;
- llvm::raw_svector_ostream Out(Msg);
- Out << Size;
- reportBug(Out.str(), C);
+ printAndReport(C, Size);
}
void ExprInspectionChecker::analyzerDumpElementCount(const CallExpr *CE,
@@ -328,11 +362,7 @@ void ExprInspectionChecker::analyzerDumpElementCount(const CallExpr *CE,
DefinedOrUnknownSVal ElementCount =
getDynamicElementCount(C.getState(), MR, C.getSValBuilder(), ElementTy);
-
- SmallString<128> Msg;
- llvm::raw_svector_ostream Out(Msg);
- Out << ElementCount;
- reportBug(Out.str(), C);
+ printAndReport(C, ElementCount);
}
void ExprInspectionChecker::analyzerPrintState(const CallExpr *CE,
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 45af22de50ae..d8f56f2f8cff 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -185,6 +185,17 @@ typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction,
ObjectsUnderConstructionMap)
+// This trait is responsible for storing the index of the element that is to be
+// constructed in the next iteration. As a result a CXXConstructExpr is only
+// stored if it is array type. Also the index is the index of the continous
+// memory region, which is important for multi-dimensional arrays. E.g:: int
+// arr[2][2]; assume arr[1][1] will be the next element under construction, so
+// the index is 3.
+typedef llvm::ImmutableMap<
+ std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
+ IndexOfElementToConstructMap;
+REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct,
+ IndexOfElementToConstructMap)
//===----------------------------------------------------------------------===//
// Engine construction and deletion.
//===----------------------------------------------------------------------===//
@@ -441,16 +452,65 @@ ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
return State;
}
+ProgramStateRef ExprEngine::setIndexOfElementToConstruct(
+ ProgramStateRef State, const CXXConstructExpr *E,
+ const LocationContext *LCtx, unsigned Idx) {
+ auto Key = std::make_pair(E, LCtx->getStackFrame());
+
+ assert(!State->contains<IndexOfElementToConstruct>(Key) || Idx > 0);
+
+ return State->set<IndexOfElementToConstruct>(Key, Idx);
+}
+
+Optional<unsigned>
+ExprEngine::getIndexOfElementToConstruct(ProgramStateRef State,
+ const CXXConstructExpr *E,
+ const LocationContext *LCtx) {
+
+ return Optional<unsigned>::create(
+ State->get<IndexOfElementToConstruct>({E, LCtx->getStackFrame()}));
+}
+
+ProgramStateRef
+ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,
+ const CXXConstructExpr *E,
+ const LocationContext *LCtx) {
+ auto Key = std::make_pair(E, LCtx->getStackFrame());
+
+ assert(E && State->contains<IndexOfElementToConstruct>(Key));
+ return State->remove<IndexOfElementToConstruct>(Key);
+}
+
ProgramStateRef
ExprEngine::addObjectUnderConstruction(ProgramStateRef State,
const ConstructionContextItem &Item,
const LocationContext *LC, SVal V) {
ConstructedObjectKey Key(Item, LC->getStackFrame());
+
+ const CXXConstructExpr *E = nullptr;
+
+ if (auto DS = dyn_cast_or_null<DeclStmt>(Item.getStmtOrNull())) {
+ if (auto VD = dyn_cast_or_null<VarDecl>(DS->getSingleDecl()))
+ E = dyn_cast<CXXConstructExpr>(VD->getInit());
+ }
+
+ if (!E && !Item.getStmtOrNull()) {
+ auto CtorInit = Item.getCXXCtorInitializer();
+ E = dyn_cast<CXXConstructExpr>(CtorInit->getInit());
+ }
+
// FIXME: Currently the state might already contain the marker due to
// incorrect handling of temporaries bound to default parameters.
- assert(!State->get<ObjectsUnderConstruction>(Key) ||
- Key.getItem().getKind() ==
- ConstructionContextItem::TemporaryDestructorKind);
+ // The state will already contain the marker if we construct elements
+ // in an array, as we visit the same statement multiple times before
+ // the array declaration. The marker is removed when we exit the
+ // constructor call.
+ assert((!State->get<ObjectsUnderConstruction>(Key) ||
+ Key.getItem().getKind() ==
+ ConstructionContextItem::TemporaryDestructorKind ||
+ State->contains<IndexOfElementToConstruct>({E, LC})) &&
+ "The object is already marked as `UnderConstruction`, when it's not "
+ "supposed to!");
return State->set<ObjectsUnderConstruction>(Key, V);
}
@@ -582,6 +642,69 @@ printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State,
}
}
+static void printIndicesOfElementsToConstructJson(
+ raw_ostream &Out, ProgramStateRef State, const char *NL,
+ const LocationContext *LCtx, const ASTContext &Context,
+ unsigned int Space = 0, bool IsDot = false) {
+ using KeyT = std::pair<const Expr *, const LocationContext *>;
+
+ PrintingPolicy PP =
+ LCtx->getAnalysisDeclContext()->getASTContext().getPrintingPolicy();
+
+ ++Space;
+ bool HasItem = false;
+
+ // Store the last key.
+ KeyT LastKey;
+ for (const auto &I : State->get<IndexOfElementToConstruct>()) {
+ const KeyT &Key = I.first;
+ if (Key.second != LCtx)
+ continue;
+
+ if (!HasItem) {
+ Out << "[" << NL;
+ HasItem = true;
+ }
+
+ LastKey = Key;
+ }
+
+ for (const auto &I : State->get<IndexOfElementToConstruct>()) {
+ const KeyT &Key = I.first;
+ unsigned Value = I.second;
+ if (Key.second != LCtx)
+ continue;
+
+ Indent(Out, Space, IsDot) << "{ ";
+
+ // Expr
+ const Expr *E = Key.first;
+ Out << "\"stmt_id\": " << E->getID(Context);
+
+ // Kind - hack to display the current index
+ Out << ", \"kind\": \"Cur: " << Value - 1 << "\"";
+
+ // Pretty-print
+ Out << ", \"pretty\": ";
+ Out << "\"" << E->getStmtClassName() << " "
+ << E->getSourceRange().printToString(Context.getSourceManager()) << " '"
+ << QualType::getAsString(E->getType().split(), PP);
+ Out << "'\"";
+
+ Out << ", \"value\": \"Next: " << Value << "\" }";
+
+ if (Key != LastKey)
+ Out << ',';
+ Out << NL;
+ }
+
+ if (HasItem)
+ Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
+ else {
+ Out << "null ";
+ }
+}
+
void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State,
const LocationContext *LCtx, const char *NL,
unsigned int Space, bool IsDot) const {
@@ -600,6 +723,23 @@ void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State,
Out << "null," << NL;
}
+ Indent(Out, Space, IsDot) << "\"index_of_element\": ";
+ if (LCtx && !State->get<IndexOfElementToConstruct>().isEmpty()) {
+ ++Space;
+
+ auto &Context = getContext();
+ Out << '[' << NL;
+ LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
+ printIndicesOfElementsToConstructJson(Out, State, NL, LC, Context, Space,
+ IsDot);
+ });
+
+ --Space;
+ Indent(Out, Space, IsDot) << "]," << NL; // End of "index_of_element".
+ } else {
+ Out << "null," << NL;
+ }
+
getCheckerManager().runCheckersForPrintStateJson(Out, State, NL, Space,
IsDot);
}
@@ -961,8 +1101,9 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
// This workaround will just run the first destructor (which will still
// invalidate the entire array).
EvalCallOptions CallOpts;
- Region = makeZeroElementRegion(state, loc::MemRegionVal(Region), varType,
- CallOpts.IsArrayCtorOrDtor).getAsRegion();
+ Region = makeElementRegion(state, loc::MemRegionVal(Region), varType,
+ CallOpts.IsArrayCtorOrDtor)
+ .getAsRegion();
VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(),
/*IsBase=*/false, Pred, Dst, CallOpts);
@@ -1045,8 +1186,7 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
// This workaround will just run the first destructor (which will still
// invalidate the entire array).
EvalCallOptions CallOpts;
- FieldVal = makeZeroElementRegion(State, FieldVal, T,
- CallOpts.IsArrayCtorOrDtor);
+ FieldVal = makeElementRegion(State, FieldVal, T, CallOpts.IsArrayCtorOrDtor);
VisitCXXDestructor(T, FieldVal.getAsRegion(), CurDtor->getBody(),
/*IsBase=*/false, Pred, Dst, CallOpts);
@@ -1105,7 +1245,7 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
CallOpts.IsArrayCtorOrDtor = true;
}
} else {
- // We'd eventually need to makeZeroElementRegion() trick here,
+ // We'd eventually need to makeElementRegion() trick here,
// but for now we don't have the respective construction contexts,
// so MR would always be null in this case. Do nothing for now.
}
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 6d979da2755f..08fac9fb2e69 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -94,15 +94,17 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
}
}
-
-SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue,
- QualType &Ty, bool &IsArray) {
+SVal ExprEngine::makeElementRegion(ProgramStateRef State, SVal LValue,
+ QualType &Ty, bool &IsArray, unsigned Idx) {
SValBuilder &SVB = State->getStateManager().getSValBuilder();
ASTContext &Ctx = SVB.getContext();
- while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
- Ty = AT->getElementType();
- LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue);
+ if (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
+ while (AT) {
+ Ty = AT->getElementType();
+ AT = dyn_cast<ArrayType>(AT->getElementType());
+ }
+ LValue = State->getLValue(Ty, SVB.makeArrayIndex(Idx), LValue);
IsArray = true;
}
@@ -111,7 +113,7 @@ SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue,
SVal ExprEngine::computeObjectUnderConstruction(
const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
- const ConstructionContext *CC, EvalCallOptions &CallOpts) {
+ const ConstructionContext *CC, EvalCallOptions &CallOpts, unsigned Idx) {
SValBuilder &SVB = getSValBuilder();
MemRegionManager &MRMgr = SVB.getRegionManager();
ASTContext &ACtx = SVB.getContext();
@@ -125,8 +127,8 @@ SVal ExprEngine::computeObjectUnderConstruction(
const auto *DS = DSCC->getDeclStmt();
const auto *Var = cast<VarDecl>(DS->getSingleDecl());
QualType Ty = Var->getType();
- return makeZeroElementRegion(State, State->getLValue(Var, LCtx), Ty,
- CallOpts.IsArrayCtorOrDtor);
+ return makeElementRegion(State, State->getLValue(Var, LCtx), Ty,
+ CallOpts.IsArrayCtorOrDtor, Idx);
}
case ConstructionContext::CXX17ElidedCopyConstructorInitializerKind:
case ConstructionContext::SimpleConstructorInitializerKind: {
@@ -158,8 +160,8 @@ SVal ExprEngine::computeObjectUnderConstruction(
}
QualType Ty = Field->getType();
- return makeZeroElementRegion(State, FieldVal, Ty,
- CallOpts.IsArrayCtorOrDtor);
+ return makeElementRegion(State, FieldVal, Ty, CallOpts.IsArrayCtorOrDtor,
+ Idx);
}
case ConstructionContext::NewAllocatedObjectKind: {
if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
@@ -172,8 +174,12 @@ SVal ExprEngine::computeObjectUnderConstruction(
// TODO: In fact, we need to call the constructor for every
// allocated element, not just the first one!
CallOpts.IsArrayCtorOrDtor = true;
- return loc::MemRegionVal(getStoreManager().GetElementZeroRegion(
- MR, NE->getType()->getPointeeType()));
+
+ auto R = MRMgr.getElementRegion(NE->getType()->getPointeeType(),
+ svalBuilder.makeArrayIndex(Idx), MR,
+ SVB.getContext());
+
+ return loc::MemRegionVal(R);
}
return V;
}
@@ -484,10 +490,6 @@ void ExprEngine::handleConstructor(const Expr *E,
}
}
- // FIXME: Handle arrays, which run the same constructor for every element.
- // For now, we just run the first constructor (which should still invalidate
- // the entire array).
-
EvalCallOptions CallOpts;
auto C = getCurrentCFGElement().getAs<CFGConstructor>();
assert(C || getCurrentCFGElement().getAs<CFGStmt>());
@@ -500,9 +502,15 @@ void ExprEngine::handleConstructor(const Expr *E,
// Inherited constructors are always base class constructors.
assert(CE && !CIE && "A complete constructor is inherited?!");
+ unsigned Idx = 0;
+ if (CE->getType()->isArrayType()) {
+ Idx = getIndexOfElementToConstruct(State, CE, LCtx).value_or(0u);
+ State = setIndexOfElementToConstruct(State, CE, LCtx, Idx + 1);
+ }
+
// The target region is found from construction context.
std::tie(State, Target) =
- handleConstructionContext(CE, State, LCtx, CC, CallOpts);
+ handleConstructionContext(CE, State, LCtx, CC, CallOpts, Idx);
break;
}
case CXXConstructExpr::CK_VirtualBase: {
@@ -894,14 +902,39 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
SVal Result = symVal;
if (CNE->isArray()) {
- // FIXME: allocating an array requires simulating the constructors.
- // For now, just return a symbolicated region.
+
if (const auto *NewReg = cast_or_null<SubRegion>(symVal.getAsRegion())) {
- QualType ObjTy = CNE->getType()->getPointeeType();
+ // If each element is initialized by their default constructor, the field
+ // values are properly placed inside the required region, however if an
+ // initializer list is used, this doesn't happen automatically.
+ auto *Init = CNE->getInitializer();
+ bool isInitList = dyn_cast_or_null<InitListExpr>(Init);
+
+ QualType ObjTy =
+ isInitList ? Init->getType() : CNE->getType()->getPointeeType();
const ElementRegion *EleReg =
- getStoreManager().GetElementZeroRegion(NewReg, ObjTy);
+ MRMgr.getElementRegion(ObjTy, svalBuilder.makeArrayIndex(0), NewReg,
+ svalBuilder.getContext());
Result = loc::MemRegionVal(EleReg);
+
+ // If the array is list initialized, we bind the initializer list to the
+ // memory region here, otherwise we would lose it.
+ if (isInitList) {
+ Bldr.takeNodes(Pred);
+ Pred = Bldr.generateNode(CNE, Pred, State);
+
+ SVal V = State->getSVal(Init, LCtx);
+ ExplodedNodeSet evaluated;
+ evalBind(evaluated, CNE, Pred, Result, V, true);
+
+ Bldr.takeNodes(Pred);
+ Bldr.addNodes(evaluated);
+
+ Pred = *evaluated.begin();
+ State = Pred->getState();
+ }
}
+
State = State->BindExpr(CNE, Pred->getLocationContext(), Result);
Bldr.generateNode(CNE, Pred, State);
return;
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index e1649f0b3df6..ebcca92a3e4e 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -227,6 +227,13 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
// Step 2: generate node with bound return value: CEBNode -> BindedRetNode.
+ // If this variable is set to 'true' the analyzer will evaluate the call
+ // statement we are about to exit again, instead of continuing the execution
+ // from the statement after the call. This is useful for non-POD type array
+ // construction where the CXXConstructExpr is referenced only once in the CFG,
+ // but we want to evaluate it as many times as many elements the array has.
+ bool ShouldRepeatCall = false;
+
// If the callee returns an expression, bind its value to CallExpr.
if (CE) {
if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
@@ -255,6 +262,12 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
SVal ThisV = state->getSVal(This);
ThisV = state->getSVal(ThisV.castAs<Loc>());
state = state->BindExpr(CCE, callerCtx, ThisV);
+
+ ShouldRepeatCall = shouldRepeatCtorCall(state, CCE, callerCtx);
+
+ if (!ShouldRepeatCall &&
+ getIndexOfElementToConstruct(state, CCE, callerCtx))
+ state = removeIndexOfElementToConstruct(state, CCE, callerCtx);
}
if (const auto *CNE = dyn_cast<CXXNewExpr>(CE)) {
@@ -358,9 +371,10 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
// Enqueue the next element in the block.
for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end();
- PSI != PSE; ++PSI) {
- Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(),
- calleeCtx->getIndex()+1);
+ PSI != PSE; ++PSI) {
+ unsigned Idx = calleeCtx->getIndex() + (ShouldRepeatCall ? 0 : 1);
+
+ Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(), Idx);
}
}
}
@@ -800,8 +814,11 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
// initializers for array fields in default move/copy constructors.
// We still allow construction into ElementRegion targets when they don't
// represent array elements.
- if (CallOpts.IsArrayCtorOrDtor)
- return CIP_DisallowedOnce;
+ if (CallOpts.IsArrayCtorOrDtor) {
+ if (!shouldInlineArrayConstruction(
+ dyn_cast<ArrayType>(CtorExpr->getType())))
+ return CIP_DisallowedOnce;
+ }
// Inlining constructors requires including initializers in the CFG.
const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
@@ -852,7 +869,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
assert(ADC->getCFGBuildOptions().AddImplicitDtors && "No CFG destructors");
(void)ADC;
- // FIXME: We don't handle constructors or destructors for arrays properly.
+ // FIXME: We don't handle destructors for arrays properly.
if (CallOpts.IsArrayCtorOrDtor)
return CIP_DisallowedOnce;
@@ -1065,6 +1082,38 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
return true;
}
+bool ExprEngine::shouldInlineArrayConstruction(const ArrayType *Type) {
+ if (!Type)
+ return false;
+
+ // FIXME: Handle other arrays types.
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(Type)) {
+ unsigned Size = getContext().getConstantArrayElementCount(CAT);
+
+ return Size <= AMgr.options.maxBlockVisitOnPath;
+ }
+
+ return false;
+}
+
+bool ExprEngine::shouldRepeatCtorCall(ProgramStateRef State,
+ const CXXConstructExpr *E,
+ const LocationContext *LCtx) {
+
+ if (!E)
+ return false;
+
+ auto Ty = E->getType();
+
+ // FIXME: Handle non constant array types
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) {
+ unsigned Size = getContext().getConstantArrayElementCount(CAT);
+ return Size > getIndexOfElementToConstruct(State, E, LCtx);
+ }
+
+ return false;
+}
+
static bool isTrivialObjectAssignment(const CallEvent &Call) {
const CXXInstanceCall *ICall = dyn_cast<CXXInstanceCall>(&Call);
if (!ICall)
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index f0cda835e07c..81c11099e93f 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -794,7 +794,11 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
if (Size.isZero())
return true;
+ if (getContext().getLangOpts().StrictFlexArrays >= 2)
+ return false;
+
const AnalyzerOptions &Opts = SVB.getAnalyzerOptions();
+ // FIXME: this option is probably redundant with -fstrict-flex-arrays=1.
if (Opts.ShouldConsiderSingleElementArraysAsFlexibleArrayMembers &&
Size.isOne())
return true;
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index e788a7a60830..2d4dfae1e750 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -1213,13 +1213,21 @@ public:
}
RangeSet VisitSymExpr(SymbolRef Sym) {
- // If we got to this function, the actual type of the symbolic
+ if (Optional<RangeSet> RS = getRangeForNegatedSym(Sym))
+ return *RS;
+ // If we've reached this line, the actual type of the symbolic
// expression is not supported for advanced inference.
// In this case, we simply backoff to the default "let's simply
// infer the range from the expression's type".
return infer(Sym->getType());
}
+ RangeSet VisitUnarySymExpr(const UnarySymExpr *USE) {
+ if (Optional<RangeSet> RS = getRangeForNegatedUnarySym(USE))
+ return *RS;
+ return infer(USE->getType());
+ }
+
RangeSet VisitSymIntExpr(const SymIntExpr *Sym) {
return VisitBinaryOperator(Sym);
}
@@ -1228,14 +1236,25 @@ public:
return VisitBinaryOperator(Sym);
}
- RangeSet VisitSymSymExpr(const SymSymExpr *Sym) {
+ RangeSet VisitSymSymExpr(const SymSymExpr *SSE) {
return intersect(
RangeFactory,
+ // If Sym is a difference of symbols A - B, then maybe we have range
+ // set stored for B - A.
+ //
+ // If we have range set stored for both A - B and B - A then
+ // calculate the effective range set by intersecting the range set
+ // for A - B and the negated range set of B - A.
+ getRangeForNegatedSymSym(SSE),
+ // If Sym is a comparison expression (except <=>),
+ // find any other comparisons with the same operands.
+ // See function description.
+ getRangeForComparisonSymbol(SSE),
// If Sym is (dis)equality, we might have some information
// on that in our equality classes data structure.
- getRangeForEqualities(Sym),
+ getRangeForEqualities(SSE),
// And we should always check what we can get from the operands.
- VisitBinaryOperator(Sym));
+ VisitBinaryOperator(SSE));
}
private:
@@ -1264,25 +1283,13 @@ private:
}
RangeSet infer(SymbolRef Sym) {
- return intersect(
- RangeFactory,
- // Of course, we should take the constraint directly associated with
- // this symbol into consideration.
- getConstraint(State, Sym),
- // If Sym is a difference of symbols A - B, then maybe we have range
- // set stored for B - A.
- //
- // If we have range set stored for both A - B and B - A then
- // calculate the effective range set by intersecting the range set
- // for A - B and the negated range set of B - A.
- getRangeForNegatedSub(Sym),
- // If Sym is a comparison expression (except <=>),
- // find any other comparisons with the same operands.
- // See function description.
- getRangeForComparisonSymbol(Sym),
- // Apart from the Sym itself, we can infer quite a lot if we look
- // into subexpressions of Sym.
- Visit(Sym));
+ return intersect(RangeFactory,
+ // Of course, we should take the constraint directly
+ // associated with this symbol into consideration.
+ getConstraint(State, Sym),
+ // Apart from the Sym itself, we can infer quite a lot if
+ // we look into subexpressions of Sym.
+ Visit(Sym));
}
RangeSet infer(EquivalenceClass Class) {
@@ -1443,38 +1450,53 @@ private:
return RangeFactory.deletePoint(Domain, IntType.getZeroValue());
}
- Optional<RangeSet> getRangeForNegatedSub(SymbolRef Sym) {
+ template <typename ProduceNegatedSymFunc>
+ Optional<RangeSet> getRangeForNegatedExpr(ProduceNegatedSymFunc F,
+ QualType T) {
// Do not negate if the type cannot be meaningfully negated.
- if (!Sym->getType()->isUnsignedIntegerOrEnumerationType() &&
- !Sym->getType()->isSignedIntegerOrEnumerationType())
+ if (!T->isUnsignedIntegerOrEnumerationType() &&
+ !T->isSignedIntegerOrEnumerationType())
return llvm::None;
- const RangeSet *NegatedRange = nullptr;
- SymbolManager &SymMgr = State->getSymbolManager();
- if (const auto *USE = dyn_cast<UnarySymExpr>(Sym)) {
- if (USE->getOpcode() == UO_Minus) {
- // Just get the operand when we negate a symbol that is already negated.
- // -(-a) == a
- NegatedRange = getConstraint(State, USE->getOperand());
- }
- } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(Sym)) {
- if (SSE->getOpcode() == BO_Sub) {
- QualType T = Sym->getType();
- SymbolRef NegatedSym =
- SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), T);
- NegatedRange = getConstraint(State, NegatedSym);
- }
- } else {
- SymbolRef NegatedSym =
- SymMgr.getUnarySymExpr(Sym, UO_Minus, Sym->getType());
- NegatedRange = getConstraint(State, NegatedSym);
- }
+ if (SymbolRef NegatedSym = F())
+ if (const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
+ return RangeFactory.negate(*NegatedRange);
- if (NegatedRange)
- return RangeFactory.negate(*NegatedRange);
return llvm::None;
}
+ Optional<RangeSet> getRangeForNegatedUnarySym(const UnarySymExpr *USE) {
+ // Just get the operand when we negate a symbol that is already negated.
+ // -(-a) == a
+ return getRangeForNegatedExpr(
+ [USE]() -> SymbolRef {
+ if (USE->getOpcode() == UO_Minus)
+ return USE->getOperand();
+ return nullptr;
+ },
+ USE->getType());
+ }
+
+ Optional<RangeSet> getRangeForNegatedSymSym(const SymSymExpr *SSE) {
+ return getRangeForNegatedExpr(
+ [SSE, State = this->State]() -> SymbolRef {
+ if (SSE->getOpcode() == BO_Sub)
+ return State->getSymbolManager().getSymSymExpr(
+ SSE->getRHS(), BO_Sub, SSE->getLHS(), SSE->getType());
+ return nullptr;
+ },
+ SSE->getType());
+ }
+
+ Optional<RangeSet> getRangeForNegatedSym(SymbolRef Sym) {
+ return getRangeForNegatedExpr(
+ [Sym, State = this->State]() {
+ return State->getSymbolManager().getUnarySymExpr(Sym, UO_Minus,
+ Sym->getType());
+ },
+ Sym->getType());
+ }
+
// Returns ranges only for binary comparison operators (except <=>)
// when left and right operands are symbolic values.
// Finds any other comparisons with the same operands.
@@ -1485,11 +1507,7 @@ private:
// It covers all possible combinations (see CmpOpTable description).
// Note that `x` and `y` can also stand for subexpressions,
// not only for actual symbols.
- Optional<RangeSet> getRangeForComparisonSymbol(SymbolRef Sym) {
- const auto *SSE = dyn_cast<SymSymExpr>(Sym);
- if (!SSE)
- return llvm::None;
-
+ Optional<RangeSet> getRangeForComparisonSymbol(const SymSymExpr *SSE) {
const BinaryOperatorKind CurrentOP = SSE->getOpcode();
// We currently do not support <=> (C++20).
@@ -1801,6 +1819,8 @@ public:
void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n",
unsigned int Space = 0, bool IsDot = false) const override;
+ void printValue(raw_ostream &Out, ProgramStateRef State,
+ SymbolRef Sym) override;
void printConstraints(raw_ostream &Out, ProgramStateRef State,
const char *NL = "\n", unsigned int Space = 0,
bool IsDot = false) const;
@@ -3154,6 +3174,13 @@ void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State,
printDisequalities(Out, State, NL, Space, IsDot);
}
+void RangeConstraintManager::printValue(raw_ostream &Out, ProgramStateRef State,
+ SymbolRef Sym) {
+ const RangeSet RS = getRange(State, Sym);
+ Out << RS.getBitWidth() << (RS.isUnsigned() ? "u:" : "s:");
+ RS.dump(Out);
+}
+
static std::string toString(const SymbolRef &Sym) {
std::string S;
llvm::raw_string_ostream O(S);
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index cf3d13ffb7ba..d90e869196eb 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -19,15 +19,16 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
-#include "clang/Basic/LLVM.h"
#include "clang/Analysis/AnalysisDeclContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
+#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
@@ -617,517 +618,478 @@ SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
}
//===----------------------------------------------------------------------===//
-// Cast methods.
-// `evalCast` is the main method
-// `evalCastKind` and `evalCastSubKind` are helpers
+// Cast method.
+// `evalCast` and its helper `EvalCastVisitor`
//===----------------------------------------------------------------------===//
-/// Cast a given SVal to another SVal using given QualType's.
-/// \param V -- SVal that should be casted.
-/// \param CastTy -- QualType that V should be casted according to.
-/// \param OriginalTy -- QualType which is associated to V. It provides
-/// additional information about what type the cast performs from.
-/// \returns the most appropriate casted SVal.
-/// Note: Many cases don't use an exact OriginalTy. It can be extracted
-/// from SVal or the cast can performs unconditionaly. Always pass OriginalTy!
-/// It can be crucial in certain cases and generates different results.
-/// FIXME: If `OriginalTy.isNull()` is true, then cast performs based on CastTy
-/// only. This behavior is uncertain and should be improved.
-SVal SValBuilder::evalCast(SVal V, QualType CastTy, QualType OriginalTy) {
- if (CastTy.isNull())
- return V;
-
- CastTy = Context.getCanonicalType(CastTy);
+namespace {
+class EvalCastVisitor : public SValVisitor<EvalCastVisitor, SVal> {
+private:
+ SValBuilder &VB;
+ ASTContext &Context;
+ QualType CastTy, OriginalTy;
- const bool IsUnknownOriginalType = OriginalTy.isNull();
- if (!IsUnknownOriginalType) {
- OriginalTy = Context.getCanonicalType(OriginalTy);
+public:
+ EvalCastVisitor(SValBuilder &VB, QualType CastTy, QualType OriginalTy)
+ : VB(VB), Context(VB.getContext()), CastTy(CastTy),
+ OriginalTy(OriginalTy) {}
- if (CastTy == OriginalTy)
+ SVal Visit(SVal V) {
+ if (CastTy.isNull())
return V;
- // FIXME: Move this check to the most appropriate
- // evalCastKind/evalCastSubKind function. For const casts, casts to void,
- // just propagate the value.
- if (!CastTy->isVariableArrayType() && !OriginalTy->isVariableArrayType())
- if (shouldBeModeledWithNoOp(Context, Context.getPointerType(CastTy),
- Context.getPointerType(OriginalTy)))
- return V;
- }
-
- // Cast SVal according to kinds.
- switch (V.getBaseKind()) {
- case SVal::UndefinedValKind:
- return evalCastKind(V.castAs<UndefinedVal>(), CastTy, OriginalTy);
- case SVal::UnknownValKind:
- return evalCastKind(V.castAs<UnknownVal>(), CastTy, OriginalTy);
- case SVal::LocKind:
- return evalCastKind(V.castAs<Loc>(), CastTy, OriginalTy);
- case SVal::NonLocKind:
- return evalCastKind(V.castAs<NonLoc>(), CastTy, OriginalTy);
- }
-
- llvm_unreachable("Unknown SVal kind");
-}
-
-SVal SValBuilder::evalCastKind(UndefinedVal V, QualType CastTy,
- QualType OriginalTy) {
- return V;
-}
-
-SVal SValBuilder::evalCastKind(UnknownVal V, QualType CastTy,
- QualType OriginalTy) {
- return V;
-}
-
-SVal SValBuilder::evalCastKind(Loc V, QualType CastTy, QualType OriginalTy) {
- switch (V.getSubKind()) {
- case loc::ConcreteIntKind:
- return evalCastSubKind(V.castAs<loc::ConcreteInt>(), CastTy, OriginalTy);
- case loc::GotoLabelKind:
- return evalCastSubKind(V.castAs<loc::GotoLabel>(), CastTy, OriginalTy);
- case loc::MemRegionValKind:
- return evalCastSubKind(V.castAs<loc::MemRegionVal>(), CastTy, OriginalTy);
- }
-
- llvm_unreachable("Unknown SVal kind");
-}
-
-SVal SValBuilder::evalCastKind(NonLoc V, QualType CastTy, QualType OriginalTy) {
- switch (V.getSubKind()) {
- case nonloc::CompoundValKind:
- return evalCastSubKind(V.castAs<nonloc::CompoundVal>(), CastTy, OriginalTy);
- case nonloc::ConcreteIntKind:
- return evalCastSubKind(V.castAs<nonloc::ConcreteInt>(), CastTy, OriginalTy);
- case nonloc::LazyCompoundValKind:
- return evalCastSubKind(V.castAs<nonloc::LazyCompoundVal>(), CastTy,
- OriginalTy);
- case nonloc::LocAsIntegerKind:
- return evalCastSubKind(V.castAs<nonloc::LocAsInteger>(), CastTy,
- OriginalTy);
- case nonloc::SymbolValKind:
- return evalCastSubKind(V.castAs<nonloc::SymbolVal>(), CastTy, OriginalTy);
- case nonloc::PointerToMemberKind:
- return evalCastSubKind(V.castAs<nonloc::PointerToMember>(), CastTy,
- OriginalTy);
- }
+ CastTy = Context.getCanonicalType(CastTy);
- llvm_unreachable("Unknown SVal kind");
-}
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ if (!IsUnknownOriginalType) {
+ OriginalTy = Context.getCanonicalType(OriginalTy);
-SVal SValBuilder::evalCastSubKind(loc::ConcreteInt V, QualType CastTy,
- QualType OriginalTy) {
- // Pointer to bool.
- if (CastTy->isBooleanType())
- return makeTruthVal(V.getValue().getBoolValue(), CastTy);
-
- // Pointer to integer.
- if (CastTy->isIntegralOrEnumerationType()) {
- llvm::APSInt Value = V.getValue();
- BasicVals.getAPSIntType(CastTy).apply(Value);
- return makeIntVal(Value);
- }
+ if (CastTy == OriginalTy)
+ return V;
- // Pointer to any pointer.
- if (Loc::isLocType(CastTy)) {
- llvm::APSInt Value = V.getValue();
- BasicVals.getAPSIntType(CastTy).apply(Value);
- return loc::ConcreteInt(BasicVals.getValue(Value));
+ // FIXME: Move this check to the most appropriate
+ // evalCastKind/evalCastSubKind function. For const casts, casts to void,
+ // just propagate the value.
+ if (!CastTy->isVariableArrayType() && !OriginalTy->isVariableArrayType())
+ if (shouldBeModeledWithNoOp(Context, Context.getPointerType(CastTy),
+ Context.getPointerType(OriginalTy)))
+ return V;
+ }
+ return SValVisitor::Visit(V);
}
+ SVal VisitUndefinedVal(UndefinedVal V) { return V; }
+ SVal VisitUnknownVal(UnknownVal V) { return V; }
+ SVal VisitLocConcreteInt(loc::ConcreteInt V) {
+ // Pointer to bool.
+ if (CastTy->isBooleanType())
+ return VB.makeTruthVal(V.getValue().getBoolValue(), CastTy);
+
+ // Pointer to integer.
+ if (CastTy->isIntegralOrEnumerationType()) {
+ llvm::APSInt Value = V.getValue();
+ VB.getBasicValueFactory().getAPSIntType(CastTy).apply(Value);
+ return VB.makeIntVal(Value);
+ }
- // Pointer to whatever else.
- return UnknownVal();
-}
-
-SVal SValBuilder::evalCastSubKind(loc::GotoLabel V, QualType CastTy,
- QualType OriginalTy) {
- // Pointer to bool.
- if (CastTy->isBooleanType())
- // Labels are always true.
- return makeTruthVal(true, CastTy);
-
- // Pointer to integer.
- if (CastTy->isIntegralOrEnumerationType()) {
- const unsigned BitWidth = Context.getIntWidth(CastTy);
- return makeLocAsInteger(V, BitWidth);
- }
+ // Pointer to any pointer.
+ if (Loc::isLocType(CastTy)) {
+ llvm::APSInt Value = V.getValue();
+ VB.getBasicValueFactory().getAPSIntType(CastTy).apply(Value);
+ return loc::ConcreteInt(VB.getBasicValueFactory().getValue(Value));
+ }
- const bool IsUnknownOriginalType = OriginalTy.isNull();
- if (!IsUnknownOriginalType) {
- // Array to pointer.
- if (isa<ArrayType>(OriginalTy))
- if (CastTy->isPointerType() || CastTy->isReferenceType())
- return UnknownVal();
+ // Pointer to whatever else.
+ return UnknownVal();
}
-
- // Pointer to any pointer.
- if (Loc::isLocType(CastTy))
- return V;
-
- // Pointer to whatever else.
- return UnknownVal();
-}
-
-static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) {
- return ty1->getPointeeType().getCanonicalType().getTypePtr() ==
- ty2->getPointeeType().getCanonicalType().getTypePtr();
-}
-
-SVal SValBuilder::evalCastSubKind(loc::MemRegionVal V, QualType CastTy,
- QualType OriginalTy) {
- // Pointer to bool.
- if (CastTy->isBooleanType()) {
- const MemRegion *R = V.getRegion();
- if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R))
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
- if (FD->isWeak())
- // FIXME: Currently we are using an extent symbol here,
- // because there are no generic region address metadata
- // symbols to use, only content metadata.
- return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR));
-
- if (const SymbolicRegion *SymR = R->getSymbolicBase()) {
- SymbolRef Sym = SymR->getSymbol();
- QualType Ty = Sym->getType();
- // This change is needed for architectures with varying
- // pointer widths. See the amdgcn opencl reproducer with
- // this change as an example: solver-sym-simplification-ptr-bool.cl
- if (!Ty->isReferenceType())
- return makeNonLoc(Sym, BO_NE, BasicVals.getZeroWithTypeSize(Ty),
- CastTy);
+ SVal VisitLocGotoLabel(loc::GotoLabel V) {
+ // Pointer to bool.
+ if (CastTy->isBooleanType())
+ // Labels are always true.
+ return VB.makeTruthVal(true, CastTy);
+
+ // Pointer to integer.
+ if (CastTy->isIntegralOrEnumerationType()) {
+ const unsigned BitWidth = Context.getIntWidth(CastTy);
+ return VB.makeLocAsInteger(V, BitWidth);
}
- // Non-symbolic memory regions are always true.
- return makeTruthVal(true, CastTy);
- }
- const bool IsUnknownOriginalType = OriginalTy.isNull();
- // Try to cast to array
- const auto *ArrayTy =
- IsUnknownOriginalType
- ? nullptr
- : dyn_cast<ArrayType>(OriginalTy.getCanonicalType());
-
- // Pointer to integer.
- if (CastTy->isIntegralOrEnumerationType()) {
- SVal Val = V;
- // Array to integer.
- if (ArrayTy) {
- // We will always decay to a pointer.
- QualType ElemTy = ArrayTy->getElementType();
- Val = StateMgr.ArrayToPointer(V, ElemTy);
- // FIXME: Keep these here for now in case we decide soon that we
- // need the original decayed type.
- // QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
- // QualType pointerTy = C.getPointerType(elemTy);
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ if (!IsUnknownOriginalType) {
+ // Array to pointer.
+ if (isa<ArrayType>(OriginalTy))
+ if (CastTy->isPointerType() || CastTy->isReferenceType())
+ return UnknownVal();
}
- const unsigned BitWidth = Context.getIntWidth(CastTy);
- return makeLocAsInteger(Val.castAs<Loc>(), BitWidth);
- }
- // Pointer to pointer.
- if (Loc::isLocType(CastTy)) {
-
- if (IsUnknownOriginalType) {
- // When retrieving symbolic pointer and expecting a non-void pointer,
- // wrap them into element regions of the expected type if necessary.
- // It is necessary to make sure that the retrieved value makes sense,
- // because there's no other cast in the AST that would tell us to cast
- // it to the correct pointer type. We might need to do that for non-void
- // pointers as well.
- // FIXME: We really need a single good function to perform casts for us
- // correctly every time we need it.
+ // Pointer to any pointer.
+ if (Loc::isLocType(CastTy))
+ return V;
+
+ // Pointer to whatever else.
+ return UnknownVal();
+ }
+ SVal VisitLocMemRegionVal(loc::MemRegionVal V) {
+ // Pointer to bool.
+ if (CastTy->isBooleanType()) {
const MemRegion *R = V.getRegion();
- if (CastTy->isPointerType() && !CastTy->isVoidPointerType()) {
- if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
- QualType SRTy = SR->getSymbol()->getType();
- if (!hasSameUnqualifiedPointeeType(SRTy, CastTy)) {
- if (auto OptMemRegV = getCastedMemRegionVal(SR, CastTy))
- return *OptMemRegV;
- }
- }
- }
- // Next fixes pointer dereference using type different from its initial
- // one. See PR37503 and PR49007 for details.
- if (const auto *ER = dyn_cast<ElementRegion>(R)) {
- if (auto OptMemRegV = getCastedMemRegionVal(ER, CastTy))
- return *OptMemRegV;
+ if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R))
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
+ if (FD->isWeak())
+ // FIXME: Currently we are using an extent symbol here,
+ // because there are no generic region address metadata
+ // symbols to use, only content metadata.
+ return nonloc::SymbolVal(
+ VB.getSymbolManager().getExtentSymbol(FTR));
+
+ if (const SymbolicRegion *SymR = R->getSymbolicBase()) {
+ SymbolRef Sym = SymR->getSymbol();
+ QualType Ty = Sym->getType();
+ // This change is needed for architectures with varying
+ // pointer widths. See the amdgcn opencl reproducer with
+ // this change as an example: solver-sym-simplification-ptr-bool.cl
+ if (!Ty->isReferenceType())
+ return VB.makeNonLoc(
+ Sym, BO_NE, VB.getBasicValueFactory().getZeroWithTypeSize(Ty),
+ CastTy);
}
-
- return V;
+ // Non-symbolic memory regions are always true.
+ return VB.makeTruthVal(true, CastTy);
}
- if (OriginalTy->isIntegralOrEnumerationType() ||
- OriginalTy->isBlockPointerType() || OriginalTy->isFunctionPointerType())
- return V;
-
- // Array to pointer.
- if (ArrayTy) {
- // Are we casting from an array to a pointer? If so just pass on
- // the decayed value.
- if (CastTy->isPointerType() || CastTy->isReferenceType()) {
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ // Try to cast to array
+ const auto *ArrayTy =
+ IsUnknownOriginalType
+ ? nullptr
+ : dyn_cast<ArrayType>(OriginalTy.getCanonicalType());
+
+ // Pointer to integer.
+ if (CastTy->isIntegralOrEnumerationType()) {
+ SVal Val = V;
+ // Array to integer.
+ if (ArrayTy) {
// We will always decay to a pointer.
QualType ElemTy = ArrayTy->getElementType();
- return StateMgr.ArrayToPointer(V, ElemTy);
+ Val = VB.getStateManager().ArrayToPointer(V, ElemTy);
+ // FIXME: Keep these here for now in case we decide soon that we
+ // need the original decayed type.
+ // QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
+ // QualType pointerTy = C.getPointerType(elemTy);
}
- // Are we casting from an array to an integer? If so, cast the decayed
- // pointer value to an integer.
- assert(CastTy->isIntegralOrEnumerationType());
+ const unsigned BitWidth = Context.getIntWidth(CastTy);
+ return VB.makeLocAsInteger(Val.castAs<Loc>(), BitWidth);
}
- // Other pointer to pointer.
- assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
- CastTy->isReferenceType());
+ // Pointer to pointer.
+ if (Loc::isLocType(CastTy)) {
- // We get a symbolic function pointer for a dereference of a function
- // pointer, but it is of function type. Example:
+ if (IsUnknownOriginalType) {
+ // When retrieving symbolic pointer and expecting a non-void pointer,
+ // wrap them into element regions of the expected type if necessary.
+ // It is necessary to make sure that the retrieved value makes sense,
+ // because there's no other cast in the AST that would tell us to cast
+ // it to the correct pointer type. We might need to do that for non-void
+ // pointers as well.
+ // FIXME: We really need a single good function to perform casts for us
+ // correctly every time we need it.
+ const MemRegion *R = V.getRegion();
+ if (CastTy->isPointerType() && !CastTy->isVoidPointerType()) {
+ if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
+ QualType SRTy = SR->getSymbol()->getType();
+
+ auto HasSameUnqualifiedPointeeType = [](QualType ty1,
+ QualType ty2) {
+ return ty1->getPointeeType().getCanonicalType().getTypePtr() ==
+ ty2->getPointeeType().getCanonicalType().getTypePtr();
+ };
+ if (!HasSameUnqualifiedPointeeType(SRTy, CastTy)) {
+ if (auto OptMemRegV = VB.getCastedMemRegionVal(SR, CastTy))
+ return *OptMemRegV;
+ }
+ }
+ }
+ // Next fixes pointer dereference using type different from its initial
+ // one. See PR37503 and PR49007 for details.
+ if (const auto *ER = dyn_cast<ElementRegion>(R)) {
+ if (auto OptMemRegV = VB.getCastedMemRegionVal(ER, CastTy))
+ return *OptMemRegV;
+ }
- // struct FPRec {
- // void (*my_func)(int * x);
- // };
- //
- // int bar(int x);
- //
- // int f1_a(struct FPRec* foo) {
- // int x;
- // (*foo->my_func)(&x);
- // return bar(x)+1; // no-warning
- // }
-
- // Get the result of casting a region to a different type.
- const MemRegion *R = V.getRegion();
- if (auto OptMemRegV = getCastedMemRegionVal(R, CastTy))
- return *OptMemRegV;
- }
+ return V;
+ }
- // Pointer to whatever else.
- // FIXME: There can be gross cases where one casts the result of a
- // function (that returns a pointer) to some other value that happens to
- // fit within that pointer value. We currently have no good way to model
- // such operations. When this happens, the underlying operation is that
- // the caller is reasoning about bits. Conceptually we are layering a
- // "view" of a location on top of those bits. Perhaps we need to be more
- // lazy about mutual possible views, even on an SVal? This may be
- // necessary for bit-level reasoning as well.
- return UnknownVal();
-}
+ if (OriginalTy->isIntegralOrEnumerationType() ||
+ OriginalTy->isBlockPointerType() ||
+ OriginalTy->isFunctionPointerType())
+ return V;
-SVal SValBuilder::evalCastSubKind(nonloc::CompoundVal V, QualType CastTy,
- QualType OriginalTy) {
- // Compound to whatever.
- return UnknownVal();
-}
+ // Array to pointer.
+ if (ArrayTy) {
+ // Are we casting from an array to a pointer? If so just pass on
+ // the decayed value.
+ if (CastTy->isPointerType() || CastTy->isReferenceType()) {
+ // We will always decay to a pointer.
+ QualType ElemTy = ArrayTy->getElementType();
+ return VB.getStateManager().ArrayToPointer(V, ElemTy);
+ }
+ // Are we casting from an array to an integer? If so, cast the decayed
+ // pointer value to an integer.
+ assert(CastTy->isIntegralOrEnumerationType());
+ }
-SVal SValBuilder::evalCastSubKind(nonloc::ConcreteInt V, QualType CastTy,
- QualType OriginalTy) {
- auto CastedValue = [V, CastTy, this]() {
- llvm::APSInt Value = V.getValue();
- BasicVals.getAPSIntType(CastTy).apply(Value);
- return Value;
- };
+ // Other pointer to pointer.
+ assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
+ CastTy->isReferenceType());
- // Integer to bool.
- if (CastTy->isBooleanType())
- return makeTruthVal(V.getValue().getBoolValue(), CastTy);
+ // We get a symbolic function pointer for a dereference of a function
+ // pointer, but it is of function type. Example:
+
+ // struct FPRec {
+ // void (*my_func)(int * x);
+ // };
+ //
+ // int bar(int x);
+ //
+ // int f1_a(struct FPRec* foo) {
+ // int x;
+ // (*foo->my_func)(&x);
+ // return bar(x)+1; // no-warning
+ // }
+
+ // Get the result of casting a region to a different type.
+ const MemRegion *R = V.getRegion();
+ if (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
+ return *OptMemRegV;
+ }
- // Integer to pointer.
- if (CastTy->isIntegralOrEnumerationType())
- return makeIntVal(CastedValue());
+ // Pointer to whatever else.
+ // FIXME: There can be gross cases where one casts the result of a
+ // function (that returns a pointer) to some other value that happens to
+ // fit within that pointer value. We currently have no good way to model
+ // such operations. When this happens, the underlying operation is that
+ // the caller is reasoning about bits. Conceptually we are layering a
+ // "view" of a location on top of those bits. Perhaps we need to be more
+ // lazy about mutual possible views, even on an SVal? This may be
+ // necessary for bit-level reasoning as well.
+ return UnknownVal();
+ }
+ SVal VisitNonLocCompoundVal(nonloc::CompoundVal V) {
+ // Compound to whatever.
+ return UnknownVal();
+ }
+ SVal VisitNonLocConcreteInt(nonloc::ConcreteInt V) {
+ auto CastedValue = [V, this]() {
+ llvm::APSInt Value = V.getValue();
+ VB.getBasicValueFactory().getAPSIntType(CastTy).apply(Value);
+ return Value;
+ };
- // Integer to pointer.
- if (Loc::isLocType(CastTy))
- return makeIntLocVal(CastedValue());
+ // Integer to bool.
+ if (CastTy->isBooleanType())
+ return VB.makeTruthVal(V.getValue().getBoolValue(), CastTy);
- // Pointer to whatever else.
- return UnknownVal();
-}
+ // Integer to pointer.
+ if (CastTy->isIntegralOrEnumerationType())
+ return VB.makeIntVal(CastedValue());
-SVal SValBuilder::evalCastSubKind(nonloc::LazyCompoundVal V, QualType CastTy,
- QualType OriginalTy) {
- // Compound to whatever.
- return UnknownVal();
-}
+ // Integer to pointer.
+ if (Loc::isLocType(CastTy))
+ return VB.makeIntLocVal(CastedValue());
-SVal SValBuilder::evalCastSubKind(nonloc::LocAsInteger V, QualType CastTy,
- QualType OriginalTy) {
- Loc L = V.getLoc();
-
- // Pointer as integer to bool.
- if (CastTy->isBooleanType())
- // Pass to Loc function.
- return evalCastKind(L, CastTy, OriginalTy);
-
- const bool IsUnknownOriginalType = OriginalTy.isNull();
- // Pointer as integer to pointer.
- if (!IsUnknownOriginalType && Loc::isLocType(CastTy) &&
- OriginalTy->isIntegralOrEnumerationType()) {
- if (const MemRegion *R = L.getAsRegion())
- if (auto OptMemRegV = getCastedMemRegionVal(R, CastTy))
- return *OptMemRegV;
- return L;
+ // Pointer to whatever else.
+ return UnknownVal();
}
-
- // Pointer as integer with region to integer/pointer.
- const MemRegion *R = L.getAsRegion();
- if (!IsUnknownOriginalType && R) {
- if (CastTy->isIntegralOrEnumerationType())
- return evalCastSubKind(loc::MemRegionVal(R), CastTy, OriginalTy);
-
- if (Loc::isLocType(CastTy)) {
- assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
- CastTy->isReferenceType());
- // Delegate to store manager to get the result of casting a region to a
- // different type. If the MemRegion* returned is NULL, this expression
- // Evaluates to UnknownVal.
- if (auto OptMemRegV = getCastedMemRegionVal(R, CastTy))
- return *OptMemRegV;
- }
- } else {
- if (Loc::isLocType(CastTy)) {
- if (IsUnknownOriginalType)
- return evalCastSubKind(loc::MemRegionVal(R), CastTy, OriginalTy);
+ SVal VisitNonLocLazyCompoundVal(nonloc::LazyCompoundVal V) {
+ // LazyCompound to whatever.
+ return UnknownVal();
+ }
+ SVal VisitNonLocLocAsInteger(nonloc::LocAsInteger V) {
+ Loc L = V.getLoc();
+
+ // Pointer as integer to bool.
+ if (CastTy->isBooleanType())
+ // Pass to Loc function.
+ return Visit(L);
+
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ // Pointer as integer to pointer.
+ if (!IsUnknownOriginalType && Loc::isLocType(CastTy) &&
+ OriginalTy->isIntegralOrEnumerationType()) {
+ if (const MemRegion *R = L.getAsRegion())
+ if (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
+ return *OptMemRegV;
return L;
}
- SymbolRef SE = nullptr;
- if (R) {
- if (const SymbolicRegion *SR =
- dyn_cast<SymbolicRegion>(R->StripCasts())) {
- SE = SR->getSymbol();
+ // Pointer as integer with region to integer/pointer.
+ const MemRegion *R = L.getAsRegion();
+ if (!IsUnknownOriginalType && R) {
+ if (CastTy->isIntegralOrEnumerationType())
+ return VisitLocMemRegionVal(loc::MemRegionVal(R));
+
+ if (Loc::isLocType(CastTy)) {
+ assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
+ CastTy->isReferenceType());
+ // Delegate to store manager to get the result of casting a region to a
+ // different type. If the MemRegion* returned is NULL, this expression
+ // Evaluates to UnknownVal.
+ if (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
+ return *OptMemRegV;
+ }
+ } else {
+ if (Loc::isLocType(CastTy)) {
+ if (IsUnknownOriginalType)
+ return VisitLocMemRegionVal(loc::MemRegionVal(R));
+ return L;
}
- }
-
- if (!CastTy->isFloatingType() || !SE || SE->getType()->isFloatingType()) {
- // FIXME: Correctly support promotions/truncations.
- const unsigned CastSize = Context.getIntWidth(CastTy);
- if (CastSize == V.getNumBits())
- return V;
- return makeLocAsInteger(L, CastSize);
- }
- }
+ SymbolRef SE = nullptr;
+ if (R) {
+ if (const SymbolicRegion *SR =
+ dyn_cast<SymbolicRegion>(R->StripCasts())) {
+ SE = SR->getSymbol();
+ }
+ }
- // Pointer as integer to whatever else.
- return UnknownVal();
-}
+ if (!CastTy->isFloatingType() || !SE || SE->getType()->isFloatingType()) {
+ // FIXME: Correctly support promotions/truncations.
+ const unsigned CastSize = Context.getIntWidth(CastTy);
+ if (CastSize == V.getNumBits())
+ return V;
-SVal SValBuilder::evalCastSubKind(nonloc::SymbolVal V, QualType CastTy,
- QualType OriginalTy) {
- SymbolRef SE = V.getSymbol();
-
- const bool IsUnknownOriginalType = OriginalTy.isNull();
- // Symbol to bool.
- if (!IsUnknownOriginalType && CastTy->isBooleanType()) {
- // Non-float to bool.
- if (Loc::isLocType(OriginalTy) ||
- OriginalTy->isIntegralOrEnumerationType() ||
- OriginalTy->isMemberPointerType()) {
- BasicValueFactory &BVF = getBasicValueFactory();
- return makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy);
+ return VB.makeLocAsInteger(L, CastSize);
+ }
}
- } else {
- // Symbol to integer, float.
- QualType T = Context.getCanonicalType(SE->getType());
- // Produce SymbolCast if CastTy and T are different integers.
- // NOTE: In the end the type of SymbolCast shall be equal to CastTy.
- if (T->isIntegralOrUnscopedEnumerationType() &&
- CastTy->isIntegralOrUnscopedEnumerationType()) {
- AnalyzerOptions &Opts =
- StateMgr.getOwningEngine().getAnalysisManager().getAnalyzerOptions();
- // If appropriate option is disabled, ignore the cast.
- // NOTE: ShouldSupportSymbolicIntegerCasts is `false` by default.
- if (!Opts.ShouldSupportSymbolicIntegerCasts)
- return V;
- return simplifySymbolCast(V, CastTy);
+ // Pointer as integer to whatever else.
+ return UnknownVal();
+ }
+ SVal VisitNonLocSymbolVal(nonloc::SymbolVal V) {
+ SymbolRef SE = V.getSymbol();
+
+ const bool IsUnknownOriginalType = OriginalTy.isNull();
+ // Symbol to bool.
+ if (!IsUnknownOriginalType && CastTy->isBooleanType()) {
+ // Non-float to bool.
+ if (Loc::isLocType(OriginalTy) ||
+ OriginalTy->isIntegralOrEnumerationType() ||
+ OriginalTy->isMemberPointerType()) {
+ BasicValueFactory &BVF = VB.getBasicValueFactory();
+ return VB.makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy);
+ }
+ } else {
+ // Symbol to integer, float.
+ QualType T = Context.getCanonicalType(SE->getType());
+
+ // Produce SymbolCast if CastTy and T are different integers.
+ // NOTE: In the end the type of SymbolCast shall be equal to CastTy.
+ if (T->isIntegralOrUnscopedEnumerationType() &&
+ CastTy->isIntegralOrUnscopedEnumerationType()) {
+ AnalyzerOptions &Opts = VB.getStateManager()
+ .getOwningEngine()
+ .getAnalysisManager()
+ .getAnalyzerOptions();
+ // If appropriate option is disabled, ignore the cast.
+ // NOTE: ShouldSupportSymbolicIntegerCasts is `false` by default.
+ if (!Opts.ShouldSupportSymbolicIntegerCasts)
+ return V;
+ return simplifySymbolCast(V, CastTy);
+ }
+ if (!Loc::isLocType(CastTy))
+ if (!IsUnknownOriginalType || !CastTy->isFloatingType() ||
+ T->isFloatingType())
+ return VB.makeNonLoc(SE, T, CastTy);
}
- if (!Loc::isLocType(CastTy))
- if (!IsUnknownOriginalType || !CastTy->isFloatingType() ||
- T->isFloatingType())
- return makeNonLoc(SE, T, CastTy);
+
+ // Symbol to pointer and whatever else.
+ return UnknownVal();
+ }
+ SVal VisitNonLocPointerToMember(nonloc::PointerToMember V) {
+ // Member pointer to whatever.
+ return V;
}
- // Symbol to pointer and whatever else.
- return UnknownVal();
-}
+ /// Reduce cast expression by removing redundant intermediate casts.
+ /// E.g.
+ /// - (char)(short)(int x) -> (char)(int x)
+ /// - (int)(int x) -> int x
+ ///
+ /// \param V -- SymbolVal, which pressumably contains SymbolCast or any symbol
+ /// that is applicable for cast operation.
+ /// \param CastTy -- QualType, which `V` shall be cast to.
+ /// \return SVal with simplified cast expression.
+ /// \note: Currently only support integral casts.
+ nonloc::SymbolVal simplifySymbolCast(nonloc::SymbolVal V, QualType CastTy) {
+ // We use seven conditions to recognize a simplification case.
+ // For the clarity let `CastTy` be `C`, SE->getType() - `T`, root type -
+ // `R`, prefix `u` for unsigned, `s` for signed, no prefix - any sign: E.g.
+ // (char)(short)(uint x)
+ // ( sC )( sT )( uR x)
+ //
+ // C === R (the same type)
+ // (char)(char x) -> (char x)
+ // (long)(long x) -> (long x)
+ // Note: Comparisons operators below are for bit width.
+ // C == T
+ // (short)(short)(int x) -> (short)(int x)
+ // (int)(long)(char x) -> (int)(char x) (sizeof(long) == sizeof(int))
+ // (long)(ullong)(char x) -> (long)(char x) (sizeof(long) ==
+ // sizeof(ullong))
+ // C < T
+ // (short)(int)(char x) -> (short)(char x)
+ // (char)(int)(short x) -> (char)(short x)
+ // (short)(int)(short x) -> (short x)
+ // C > T > uR
+ // (int)(short)(uchar x) -> (int)(uchar x)
+ // (uint)(short)(uchar x) -> (uint)(uchar x)
+ // (int)(ushort)(uchar x) -> (int)(uchar x)
+ // C > sT > sR
+ // (int)(short)(char x) -> (int)(char x)
+ // (uint)(short)(char x) -> (uint)(char x)
+ // C > sT == sR
+ // (int)(char)(char x) -> (int)(char x)
+ // (uint)(short)(short x) -> (uint)(short x)
+ // C > uT == uR
+ // (int)(uchar)(uchar x) -> (int)(uchar x)
+ // (uint)(ushort)(ushort x) -> (uint)(ushort x)
+ // (llong)(ulong)(uint x) -> (llong)(uint x) (sizeof(ulong) ==
+ // sizeof(uint))
+
+ SymbolRef SE = V.getSymbol();
+ QualType T = Context.getCanonicalType(SE->getType());
-SVal SValBuilder::evalCastSubKind(nonloc::PointerToMember V, QualType CastTy,
- QualType OriginalTy) {
- // Member pointer to whatever.
- return V;
-}
+ if (T == CastTy)
+ return V;
-nonloc::SymbolVal SValBuilder::simplifySymbolCast(nonloc::SymbolVal V,
- QualType CastTy) {
- // We use seven conditions to recognize a simplification case.
- // For the clarity let `CastTy` be `C`, SE->getType() - `T`, root type - `R`,
- // prefix `u` for unsigned, `s` for signed, no prefix - any sign:
- // E.g. (char)(short)(uint x)
- // ( sC )( sT )( uR x)
- //
- // C === R (the same type)
- // (char)(char x) -> (char x)
- // (long)(long x) -> (long x)
- // Note: Comparisons operators below are for bit width.
- // C == T
- // (short)(short)(int x) -> (short)(int x)
- // (int)(long)(char x) -> (int)(char x) (sizeof(long) == sizeof(int))
- // (long)(ullong)(char x) -> (long)(char x) (sizeof(long) == sizeof(ullong))
- // C < T
- // (short)(int)(char x) -> (short)(char x)
- // (char)(int)(short x) -> (char)(short x)
- // (short)(int)(short x) -> (short x)
- // C > T > uR
- // (int)(short)(uchar x) -> (int)(uchar x)
- // (uint)(short)(uchar x) -> (uint)(uchar x)
- // (int)(ushort)(uchar x) -> (int)(uchar x)
- // C > sT > sR
- // (int)(short)(char x) -> (int)(char x)
- // (uint)(short)(char x) -> (uint)(char x)
- // C > sT == sR
- // (int)(char)(char x) -> (int)(char x)
- // (uint)(short)(short x) -> (uint)(short x)
- // C > uT == uR
- // (int)(uchar)(uchar x) -> (int)(uchar x)
- // (uint)(ushort)(ushort x) -> (uint)(ushort x)
- // (llong)(ulong)(uint x) -> (llong)(uint x) (sizeof(ulong) == sizeof(uint))
-
- SymbolRef SE = V.getSymbol();
- QualType T = Context.getCanonicalType(SE->getType());
-
- if (T == CastTy)
- return V;
+ if (!isa<SymbolCast>(SE))
+ return VB.makeNonLoc(SE, T, CastTy);
- if (!isa<SymbolCast>(SE))
- return makeNonLoc(SE, T, CastTy);
+ SymbolRef RootSym = cast<SymbolCast>(SE)->getOperand();
+ QualType RT = RootSym->getType().getCanonicalType();
- SymbolRef RootSym = cast<SymbolCast>(SE)->getOperand();
- QualType RT = RootSym->getType().getCanonicalType();
+ // FIXME support simplification from non-integers.
+ if (!RT->isIntegralOrEnumerationType())
+ return VB.makeNonLoc(SE, T, CastTy);
- // FIXME support simplification from non-integers.
- if (!RT->isIntegralOrEnumerationType())
- return makeNonLoc(SE, T, CastTy);
+ BasicValueFactory &BVF = VB.getBasicValueFactory();
+ APSIntType CTy = BVF.getAPSIntType(CastTy);
+ APSIntType TTy = BVF.getAPSIntType(T);
- BasicValueFactory &BVF = getBasicValueFactory();
- APSIntType CTy = BVF.getAPSIntType(CastTy);
- APSIntType TTy = BVF.getAPSIntType(T);
+ const auto WC = CTy.getBitWidth();
+ const auto WT = TTy.getBitWidth();
- const auto WC = CTy.getBitWidth();
- const auto WT = TTy.getBitWidth();
+ if (WC <= WT) {
+ const bool isSameType = (RT == CastTy);
+ if (isSameType)
+ return nonloc::SymbolVal(RootSym);
+ return VB.makeNonLoc(RootSym, RT, CastTy);
+ }
- if (WC <= WT) {
- const bool isSameType = (RT == CastTy);
- if (isSameType)
- return nonloc::SymbolVal(RootSym);
- return makeNonLoc(RootSym, RT, CastTy);
- }
+ APSIntType RTy = BVF.getAPSIntType(RT);
+ const auto WR = RTy.getBitWidth();
+ const bool UT = TTy.isUnsigned();
+ const bool UR = RTy.isUnsigned();
- APSIntType RTy = BVF.getAPSIntType(RT);
- const auto WR = RTy.getBitWidth();
- const bool UT = TTy.isUnsigned();
- const bool UR = RTy.isUnsigned();
+ if (((WT > WR) && (UR || !UT)) || ((WT == WR) && (UT == UR)))
+ return VB.makeNonLoc(RootSym, RT, CastTy);
- if (((WT > WR) && (UR || !UT)) || ((WT == WR) && (UT == UR)))
- return makeNonLoc(RootSym, RT, CastTy);
+ return VB.makeNonLoc(SE, T, CastTy);
+ }
+};
+} // end anonymous namespace
- return makeNonLoc(SE, T, CastTy);
+/// Cast a given SVal to another SVal using given QualType's.
+/// \param V -- SVal that should be casted.
+/// \param CastTy -- QualType that V should be casted according to.
+/// \param OriginalTy -- QualType which is associated to V. It provides
+/// additional information about what type the cast performs from.
+/// \returns the most appropriate casted SVal.
+/// Note: Many cases don't use an exact OriginalTy. It can be extracted
+/// from SVal or the cast can performs unconditionaly. Always pass OriginalTy!
+/// It can be crucial in certain cases and generates different results.
+/// FIXME: If `OriginalTy.isNull()` is true, then cast performs based on CastTy
+/// only. This behavior is uncertain and should be improved.
+SVal SValBuilder::evalCast(SVal V, QualType CastTy, QualType OriginalTy) {
+ EvalCastVisitor TRV{*this, CastTy, OriginalTy};
+ return TRV.Visit(V);
}
diff --git a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp
index 67913a55b3dc..31725926cd0d 100644
--- a/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp
+++ b/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SVals.cpp
@@ -109,6 +109,14 @@ SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const {
return getAsLocSymbol(IncludeBaseRegions);
}
+const llvm::APSInt *SVal::getAsInteger() const {
+ if (auto CI = getAs<nonloc::ConcreteInt>())
+ return &CI->getValue();
+ if (auto CI = getAs<loc::ConcreteInt>())
+ return &CI->getValue();
+ return nullptr;
+}
+
const MemRegion *SVal::getAsRegion() const {
if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
return X->getRegion();
@@ -136,6 +144,8 @@ public:
}
template <class ConcreteInt> QualType VisitConcreteInt(ConcreteInt CI) {
const llvm::APSInt &Value = CI.getValue();
+ if (1 == Value.getBitWidth())
+ return Context.BoolTy;
return Context.getIntTypeForBitwidth(Value.getBitWidth(), Value.isSigned());
}
QualType VisitLocConcreteInt(loc::ConcreteInt CI) {
diff --git a/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
index 43127ea2df98..411fd9676ffd 100644
--- a/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
@@ -50,8 +50,9 @@ FullDependencies::getCommandLineWithoutModulePaths() const {
}
DependencyScanningTool::DependencyScanningTool(
- DependencyScanningService &Service)
- : Worker(Service) {}
+ DependencyScanningService &Service,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
+ : Worker(Service, std::move(FS)) {}
llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
const std::vector<std::string> &CommandLine, StringRef CWD,
diff --git a/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index e7d1375c83f0..474808d888ec 100644
--- a/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -264,7 +264,8 @@ private:
} // end anonymous namespace
DependencyScanningWorker::DependencyScanningWorker(
- DependencyScanningService &Service)
+ DependencyScanningService &Service,
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
: Format(Service.getFormat()), OptimizeArgs(Service.canOptimizeArgs()) {
PCHContainerOps = std::make_shared<PCHContainerOperations>();
PCHContainerOps->registerReader(
@@ -274,8 +275,8 @@ DependencyScanningWorker::DependencyScanningWorker(
PCHContainerOps->registerWriter(
std::make_unique<ObjectFilePCHContainerWriter>());
- auto OverlayFS = llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(
- llvm::vfs::createPhysicalFileSystem());
+ auto OverlayFS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(std::move(FS));
InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
OverlayFS->pushOverlay(InMemoryFS);
RealFS = OverlayFS;
diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp
index 484cf61664fe..041cc4f939d9 100644
--- a/contrib/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -27,6 +27,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Tooling/Syntax/Nodes.h"
+#include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
#include "clang/Tooling/Syntax/Tokens.h"
#include "clang/Tooling/Syntax/Tree.h"
#include "llvm/ADT/ArrayRef.h"
@@ -365,21 +366,24 @@ private:
/// Call finalize() to finish building the tree and consume the root node.
class syntax::TreeBuilder {
public:
- TreeBuilder(syntax::Arena &Arena) : Arena(Arena), Pending(Arena) {
- for (const auto &T : Arena.getTokenBuffer().expandedTokens())
+ TreeBuilder(syntax::Arena &Arena, TokenBufferTokenManager& TBTM)
+ : Arena(Arena),
+ TBTM(TBTM),
+ Pending(Arena, TBTM.tokenBuffer()) {
+ for (const auto &T : TBTM.tokenBuffer().expandedTokens())
LocationToToken.insert({T.location(), &T});
}
llvm::BumpPtrAllocator &allocator() { return Arena.getAllocator(); }
const SourceManager &sourceManager() const {
- return Arena.getSourceManager();
+ return TBTM.sourceManager();
}
/// Populate children for \p New node, assuming it covers tokens from \p
/// Range.
void foldNode(ArrayRef<syntax::Token> Range, syntax::Tree *New, ASTPtr From) {
assert(New);
- Pending.foldChildren(Arena, Range, New);
+ Pending.foldChildren(TBTM.tokenBuffer(), Range, New);
if (From)
Mapping.add(From, New);
}
@@ -392,7 +396,7 @@ public:
void foldNode(llvm::ArrayRef<syntax::Token> Range, syntax::Tree *New,
NestedNameSpecifierLoc From) {
assert(New);
- Pending.foldChildren(Arena, Range, New);
+ Pending.foldChildren(TBTM.tokenBuffer(), Range, New);
if (From)
Mapping.add(From, New);
}
@@ -403,7 +407,7 @@ public:
ASTPtr From) {
assert(New);
auto ListRange = Pending.shrinkToFitList(SuperRange);
- Pending.foldChildren(Arena, ListRange, New);
+ Pending.foldChildren(TBTM.tokenBuffer(), ListRange, New);
if (From)
Mapping.add(From, New);
}
@@ -434,12 +438,12 @@ public:
/// Finish building the tree and consume the root node.
syntax::TranslationUnit *finalize() && {
- auto Tokens = Arena.getTokenBuffer().expandedTokens();
+ auto Tokens = TBTM.tokenBuffer().expandedTokens();
assert(!Tokens.empty());
assert(Tokens.back().kind() == tok::eof);
// Build the root of the tree, consuming all the children.
- Pending.foldChildren(Arena, Tokens.drop_back(),
+ Pending.foldChildren(TBTM.tokenBuffer(), Tokens.drop_back(),
new (Arena.getAllocator()) syntax::TranslationUnit);
auto *TU = cast<syntax::TranslationUnit>(std::move(Pending).finalize());
@@ -464,7 +468,7 @@ public:
assert(First.isValid());
assert(Last.isValid());
assert(First == Last ||
- Arena.getSourceManager().isBeforeInTranslationUnit(First, Last));
+ TBTM.sourceManager().isBeforeInTranslationUnit(First, Last));
return llvm::makeArrayRef(findToken(First), std::next(findToken(Last)));
}
@@ -564,15 +568,16 @@ private:
///
/// Ensures that added nodes properly nest and cover the whole token stream.
struct Forest {
- Forest(syntax::Arena &A) {
- assert(!A.getTokenBuffer().expandedTokens().empty());
- assert(A.getTokenBuffer().expandedTokens().back().kind() == tok::eof);
+ Forest(syntax::Arena &A, const syntax::TokenBuffer &TB) {
+ assert(!TB.expandedTokens().empty());
+ assert(TB.expandedTokens().back().kind() == tok::eof);
// Create all leaf nodes.
// Note that we do not have 'eof' in the tree.
- for (const auto &T : A.getTokenBuffer().expandedTokens().drop_back()) {
- auto *L = new (A.getAllocator()) syntax::Leaf(&T);
+ for (const auto &T : TB.expandedTokens().drop_back()) {
+ auto *L = new (A.getAllocator())
+ syntax::Leaf(reinterpret_cast<TokenManager::Key>(&T));
L->Original = true;
- L->CanModify = A.getTokenBuffer().spelledForExpanded(T).has_value();
+ L->CanModify = TB.spelledForExpanded(T).has_value();
Trees.insert(Trees.end(), {&T, L});
}
}
@@ -620,8 +625,8 @@ private:
}
/// Add \p Node to the forest and attach child nodes based on \p Tokens.
- void foldChildren(const syntax::Arena &A, ArrayRef<syntax::Token> Tokens,
- syntax::Tree *Node) {
+ void foldChildren(const syntax::TokenBuffer &TB,
+ ArrayRef<syntax::Token> Tokens, syntax::Tree *Node) {
// Attach children to `Node`.
assert(Node->getFirstChild() == nullptr && "node already has children");
@@ -646,7 +651,7 @@ private:
// Mark that this node came from the AST and is backed by the source code.
Node->Original = true;
Node->CanModify =
- A.getTokenBuffer().spelledForExpanded(Tokens).has_value();
+ TB.spelledForExpanded(Tokens).has_value();
Trees.erase(BeginChildren, EndChildren);
Trees.insert({FirstToken, Node});
@@ -660,18 +665,18 @@ private:
return Root;
}
- std::string str(const syntax::Arena &A) const {
+ std::string str(const syntax::TokenBufferTokenManager &STM) const {
std::string R;
for (auto It = Trees.begin(); It != Trees.end(); ++It) {
unsigned CoveredTokens =
It != Trees.end()
? (std::next(It)->first - It->first)
- : A.getTokenBuffer().expandedTokens().end() - It->first;
+ : STM.tokenBuffer().expandedTokens().end() - It->first;
R += std::string(
formatv("- '{0}' covers '{1}'+{2} tokens\n", It->second->getKind(),
- It->first->text(A.getSourceManager()), CoveredTokens));
- R += It->second->dump(A.getSourceManager());
+ It->first->text(STM.sourceManager()), CoveredTokens));
+ R += It->second->dump(STM);
}
return R;
}
@@ -684,9 +689,10 @@ private:
};
/// For debugging purposes.
- std::string str() { return Pending.str(Arena); }
+ std::string str() { return Pending.str(TBTM); }
syntax::Arena &Arena;
+ TokenBufferTokenManager& TBTM;
/// To quickly find tokens by their start location.
llvm::DenseMap<SourceLocation, const syntax::Token *> LocationToToken;
Forest Pending;
@@ -1718,7 +1724,7 @@ void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) {
markExprChild(ChildExpr, NodeRole::Expression);
ChildNode = new (allocator()) syntax::ExpressionStatement;
// (!) 'getStmtRange()' ensures this covers a trailing semicolon.
- Pending.foldChildren(Arena, getStmtRange(Child), ChildNode);
+ Pending.foldChildren(TBTM.tokenBuffer(), getStmtRange(Child), ChildNode);
} else {
ChildNode = Mapping.find(Child);
}
@@ -1745,8 +1751,9 @@ const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const {
}
syntax::TranslationUnit *syntax::buildSyntaxTree(Arena &A,
+ TokenBufferTokenManager& TBTM,
ASTContext &Context) {
- TreeBuilder Builder(A);
+ TreeBuilder Builder(A, TBTM);
BuildTreeVisitor(Context, Builder).TraverseAST(Context);
return std::move(Builder).finalize();
}
diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/ComputeReplacements.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/ComputeReplacements.cpp
index 31e1a40c74b6..08e09e4ebdbf 100644
--- a/contrib/llvm-project/clang/lib/Tooling/Syntax/ComputeReplacements.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/ComputeReplacements.cpp
@@ -7,7 +7,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/Core/Replacement.h"
#include "clang/Tooling/Syntax/Mutations.h"
+#include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
#include "clang/Tooling/Syntax/Tokens.h"
+#include "clang/Tooling/Syntax/Tree.h"
#include "llvm/Support/Error.h"
using namespace clang;
@@ -16,10 +18,13 @@ namespace {
using ProcessTokensFn = llvm::function_ref<void(llvm::ArrayRef<syntax::Token>,
bool /*IsOriginal*/)>;
/// Enumerates spans of tokens from the tree consecutively laid out in memory.
-void enumerateTokenSpans(const syntax::Tree *Root, ProcessTokensFn Callback) {
+void enumerateTokenSpans(const syntax::Tree *Root,
+ const syntax::TokenBufferTokenManager &STM,
+ ProcessTokensFn Callback) {
struct Enumerator {
- Enumerator(ProcessTokensFn Callback)
- : SpanBegin(nullptr), SpanEnd(nullptr), SpanIsOriginal(false),
+ Enumerator(const syntax::TokenBufferTokenManager &STM,
+ ProcessTokensFn Callback)
+ : STM(STM), SpanBegin(nullptr), SpanEnd(nullptr), SpanIsOriginal(false),
Callback(Callback) {}
void run(const syntax::Tree *Root) {
@@ -39,7 +44,8 @@ void enumerateTokenSpans(const syntax::Tree *Root, ProcessTokensFn Callback) {
}
auto *L = cast<syntax::Leaf>(N);
- if (SpanEnd == L->getToken() && SpanIsOriginal == L->isOriginal()) {
+ if (SpanEnd == STM.getToken(L->getTokenKey()) &&
+ SpanIsOriginal == L->isOriginal()) {
// Extend the current span.
++SpanEnd;
return;
@@ -48,24 +54,25 @@ void enumerateTokenSpans(const syntax::Tree *Root, ProcessTokensFn Callback) {
if (SpanBegin)
Callback(llvm::makeArrayRef(SpanBegin, SpanEnd), SpanIsOriginal);
// Start recording a new span.
- SpanBegin = L->getToken();
+ SpanBegin = STM.getToken(L->getTokenKey());
SpanEnd = SpanBegin + 1;
SpanIsOriginal = L->isOriginal();
}
+ const syntax::TokenBufferTokenManager &STM;
const syntax::Token *SpanBegin;
const syntax::Token *SpanEnd;
bool SpanIsOriginal;
ProcessTokensFn Callback;
};
- return Enumerator(Callback).run(Root);
+ return Enumerator(STM, Callback).run(Root);
}
-syntax::FileRange rangeOfExpanded(const syntax::Arena &A,
+syntax::FileRange rangeOfExpanded(const syntax::TokenBufferTokenManager &STM,
llvm::ArrayRef<syntax::Token> Expanded) {
- const auto &Buffer = A.getTokenBuffer();
- const auto &SM = A.getSourceManager();
+ const auto &Buffer = STM.tokenBuffer();
+ const auto &SM = STM.sourceManager();
// Check that \p Expanded actually points into expanded tokens.
assert(Buffer.expandedTokens().begin() <= Expanded.begin());
@@ -83,10 +90,10 @@ syntax::FileRange rangeOfExpanded(const syntax::Arena &A,
} // namespace
tooling::Replacements
-syntax::computeReplacements(const syntax::Arena &A,
+syntax::computeReplacements(const TokenBufferTokenManager &TBTM,
const syntax::TranslationUnit &TU) {
- const auto &Buffer = A.getTokenBuffer();
- const auto &SM = A.getSourceManager();
+ const auto &Buffer = TBTM.tokenBuffer();
+ const auto &SM = TBTM.sourceManager();
tooling::Replacements Replacements;
// Text inserted by the replacement we are building now.
@@ -95,13 +102,13 @@ syntax::computeReplacements(const syntax::Arena &A,
if (ReplacedRange.empty() && Replacement.empty())
return;
llvm::cantFail(Replacements.add(tooling::Replacement(
- SM, rangeOfExpanded(A, ReplacedRange).toCharRange(SM), Replacement)));
+ SM, rangeOfExpanded(TBTM, ReplacedRange).toCharRange(SM),
+ Replacement)));
Replacement = "";
};
-
const syntax::Token *NextOriginal = Buffer.expandedTokens().begin();
enumerateTokenSpans(
- &TU, [&](llvm::ArrayRef<syntax::Token> Tokens, bool IsOriginal) {
+ &TU, TBTM, [&](llvm::ArrayRef<syntax::Token> Tokens, bool IsOriginal) {
if (!IsOriginal) {
Replacement +=
syntax::Token::range(SM, Tokens.front(), Tokens.back()).text(SM);
diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp
index f8a652219b22..824f1942532d 100644
--- a/contrib/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/Mutations.cpp
@@ -77,7 +77,8 @@ public:
}
};
-void syntax::removeStatement(syntax::Arena &A, syntax::Statement *S) {
+void syntax::removeStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM,
+ syntax::Statement *S) {
assert(S);
assert(S->canModify());
@@ -90,5 +91,5 @@ void syntax::removeStatement(syntax::Arena &A, syntax::Statement *S) {
if (isa<EmptyStatement>(S))
return; // already an empty statement, nothing to do.
- MutationsImpl::replace(S, createEmptyStatement(A));
+ MutationsImpl::replace(S, createEmptyStatement(A, TBTM));
}
diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/Nodes.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/Nodes.cpp
index fc6f8ef1a82c..d0c1e9297cfa 100644
--- a/contrib/llvm-project/clang/lib/Tooling/Syntax/Nodes.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/Nodes.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Tooling/Syntax/Nodes.h"
-#include "clang/Basic/TokenKinds.h"
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp
index ef6492882be6..39c19951ae76 100644
--- a/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp
@@ -8,6 +8,8 @@
#include "clang/Basic/TokenKinds.h"
#include "clang/Tooling/Syntax/BuildTree.h"
#include "clang/Tooling/Syntax/Tree.h"
+#include "clang/Tooling/Syntax/Tokens.h"
+#include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
using namespace clang;
@@ -27,35 +29,40 @@ public:
}
static std::pair<FileID, ArrayRef<Token>>
- lexBuffer(syntax::Arena &A, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
- return A.lexBuffer(std::move(Buffer));
+ lexBuffer(TokenBufferTokenManager &TBTM,
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
+ return TBTM.lexBuffer(std::move(Buffer));
}
};
// FIXME: `createLeaf` is based on `syntax::tokenize` internally, as such it
// doesn't support digraphs or line continuations.
-syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K,
- StringRef Spelling) {
+syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A,
+ TokenBufferTokenManager &TBTM,
+ tok::TokenKind K, StringRef Spelling) {
auto Tokens =
- FactoryImpl::lexBuffer(A, llvm::MemoryBuffer::getMemBufferCopy(Spelling))
+ FactoryImpl::lexBuffer(TBTM, llvm::MemoryBuffer::getMemBufferCopy(Spelling))
.second;
assert(Tokens.size() == 1);
assert(Tokens.front().kind() == K &&
"spelling is not lexed into the expected kind of token");
- auto *Leaf = new (A.getAllocator()) syntax::Leaf(Tokens.begin());
+ auto *Leaf = new (A.getAllocator()) syntax::Leaf(
+ reinterpret_cast<TokenManager::Key>(Tokens.begin()));
syntax::FactoryImpl::setCanModify(Leaf);
Leaf->assertInvariants();
return Leaf;
}
-syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K) {
+syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A,
+ TokenBufferTokenManager &TBTM,
+ tok::TokenKind K) {
const auto *Spelling = tok::getPunctuatorSpelling(K);
if (!Spelling)
Spelling = tok::getKeywordSpelling(K);
assert(Spelling &&
"Cannot infer the spelling of the token from its token kind.");
- return createLeaf(A, K, Spelling);
+ return createLeaf(A, TBTM, K, Spelling);
}
namespace {
@@ -208,24 +215,25 @@ syntax::Tree *clang::syntax::createTree(
}
syntax::Node *clang::syntax::deepCopyExpandingMacros(syntax::Arena &A,
+ TokenBufferTokenManager &TBTM,
const syntax::Node *N) {
if (const auto *L = dyn_cast<syntax::Leaf>(N))
// `L->getToken()` gives us the expanded token, thus we implicitly expand
// any macros here.
- return createLeaf(A, L->getToken()->kind(),
- L->getToken()->text(A.getSourceManager()));
+ return createLeaf(A, TBTM, TBTM.getToken(L->getTokenKey())->kind(),
+ TBTM.getText(L->getTokenKey()));
const auto *T = cast<syntax::Tree>(N);
std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children;
for (const auto *Child = T->getFirstChild(); Child;
Child = Child->getNextSibling())
- Children.push_back({deepCopyExpandingMacros(A, Child), Child->getRole()});
+ Children.push_back({deepCopyExpandingMacros(A, TBTM, Child), Child->getRole()});
return createTree(A, Children, N->getKind());
}
-syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) {
+syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM) {
return cast<EmptyStatement>(
- createTree(A, {{createLeaf(A, tok::semi), NodeRole::Unknown}},
+ createTree(A, {{createLeaf(A, TBTM, tok::semi), NodeRole::Unknown}},
NodeKind::EmptyStatement));
}
diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp
new file mode 100644
index 000000000000..a06f7e2900d4
--- /dev/null
+++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/TokenBufferTokenManager.cpp
@@ -0,0 +1,25 @@
+//===- TokenBufferTokenManager.cpp ----------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
+
+namespace clang {
+namespace syntax {
+constexpr llvm::StringLiteral syntax::TokenBufferTokenManager::Kind;
+
+std::pair<FileID, ArrayRef<syntax::Token>>
+syntax::TokenBufferTokenManager::lexBuffer(
+ std::unique_ptr<llvm::MemoryBuffer> Input) {
+ auto FID = SM.createFileID(std::move(Input));
+ auto It = ExtraTokens.try_emplace(FID, tokenize(FID, SM, LangOpts));
+ assert(It.second && "duplicate FileID");
+ return {FID, It.first->second};
+}
+
+} // namespace syntax
+} // namespace clang
diff --git a/contrib/llvm-project/clang/lib/Tooling/Syntax/Tree.cpp b/contrib/llvm-project/clang/lib/Tooling/Syntax/Tree.cpp
index 981bac508f73..20f7bd087aa0 100644
--- a/contrib/llvm-project/clang/lib/Tooling/Syntax/Tree.cpp
+++ b/contrib/llvm-project/clang/lib/Tooling/Syntax/Tree.cpp
@@ -8,9 +8,8 @@
#include "clang/Tooling/Syntax/Tree.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Tooling/Syntax/Nodes.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Casting.h"
#include <cassert>
@@ -33,25 +32,7 @@ static void traverse(syntax::Node *N,
}
} // namespace
-syntax::Arena::Arena(SourceManager &SourceMgr, const LangOptions &LangOpts,
- const TokenBuffer &Tokens)
- : SourceMgr(SourceMgr), LangOpts(LangOpts), Tokens(Tokens) {}
-
-const syntax::TokenBuffer &syntax::Arena::getTokenBuffer() const {
- return Tokens;
-}
-
-std::pair<FileID, ArrayRef<syntax::Token>>
-syntax::Arena::lexBuffer(std::unique_ptr<llvm::MemoryBuffer> Input) {
- auto FID = SourceMgr.createFileID(std::move(Input));
- auto It = ExtraTokens.try_emplace(FID, tokenize(FID, SourceMgr, LangOpts));
- assert(It.second && "duplicate FileID");
- return {FID, It.first->second};
-}
-
-syntax::Leaf::Leaf(const syntax::Token *Tok) : Node(NodeKind::Leaf), Tok(Tok) {
- assert(Tok != nullptr);
-}
+syntax::Leaf::Leaf(syntax::TokenManager::Key K) : Node(NodeKind::Leaf), K(K) {}
syntax::Node::Node(NodeKind Kind)
: Parent(nullptr), NextSibling(nullptr), PreviousSibling(nullptr),
@@ -190,20 +171,8 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *Begin, Node *End,
}
namespace {
-static void dumpLeaf(raw_ostream &OS, const syntax::Leaf *L,
- const SourceManager &SM) {
- assert(L);
- const auto *Token = L->getToken();
- assert(Token);
- // Handle 'eof' separately, calling text() on it produces an empty string.
- if (Token->kind() == tok::eof)
- OS << "<eof>";
- else
- OS << Token->text(SM);
-}
-
static void dumpNode(raw_ostream &OS, const syntax::Node *N,
- const SourceManager &SM, llvm::BitVector IndentMask) {
+ const syntax::TokenManager &TM, llvm::BitVector IndentMask) {
auto DumpExtraInfo = [&OS](const syntax::Node *N) {
if (N->getRole() != syntax::NodeRole::Unknown)
OS << " " << N->getRole();
@@ -216,7 +185,7 @@ static void dumpNode(raw_ostream &OS, const syntax::Node *N,
assert(N);
if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
OS << "'";
- dumpLeaf(OS, L, SM);
+ OS << TM.getText(L->getTokenKey());
OS << "'";
DumpExtraInfo(N);
OS << "\n";
@@ -242,25 +211,25 @@ static void dumpNode(raw_ostream &OS, const syntax::Node *N,
OS << "|-";
IndentMask.push_back(true);
}
- dumpNode(OS, &It, SM, IndentMask);
+ dumpNode(OS, &It, TM, IndentMask);
IndentMask.pop_back();
}
}
} // namespace
-std::string syntax::Node::dump(const SourceManager &SM) const {
+std::string syntax::Node::dump(const TokenManager &TM) const {
std::string Str;
llvm::raw_string_ostream OS(Str);
- dumpNode(OS, this, SM, /*IndentMask=*/{});
+ dumpNode(OS, this, TM, /*IndentMask=*/{});
return std::move(OS.str());
}
-std::string syntax::Node::dumpTokens(const SourceManager &SM) const {
+std::string syntax::Node::dumpTokens(const TokenManager &TM) const {
std::string Storage;
llvm::raw_string_ostream OS(Storage);
traverse(this, [&](const syntax::Node *N) {
if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
- dumpLeaf(OS, L, SM);
+ OS << TM.getText(L->getTokenKey());
OS << " ";
}
});
@@ -297,7 +266,8 @@ void syntax::Node::assertInvariants() const {
C.getRole() == NodeRole::ListDelimiter);
if (C.getRole() == NodeRole::ListDelimiter) {
assert(isa<Leaf>(C));
- assert(cast<Leaf>(C).getToken()->kind() == L->getDelimiterTokenKind());
+ // FIXME: re-enable it when there is way to retrieve token kind in Leaf.
+ // assert(cast<Leaf>(C).getToken()->kind() == L->getDelimiterTokenKind());
}
}