summaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-03-18 18:20:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-03-18 18:20:05 +0000
commit2fc9bb9ce23aec06620745773d24e59944b87ffc (patch)
tree0726fa11e6594591f34578ba035ea82a69fc0393 /clang/lib
parentd652fd2996ce31dfd35dd2a9c58bf051ca7fff44 (diff)
Notes
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTImporter.cpp2
-rw-r--r--clang/lib/Lex/Pragma.cpp3
-rw-r--r--clang/lib/Sema/SemaExpr.cpp17
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp54
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp6
-rw-r--r--clang/lib/Sema/TreeTransform.h23
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp67
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp2
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp2
10 files changed, 150 insertions, 28 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index f42361500a91..ab4e961dcd4c 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6726,7 +6726,7 @@ ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) {
return new (Importer.getToContext())
StmtExpr(ToSubStmt, ToType, ToLParenLoc, ToRParenLoc,
- E->isInstantiationDependent());
+ E->getTemplateDepth());
}
ExpectedStmt ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) {
diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp
index a8cd18b123b0..57a95815488e 100644
--- a/clang/lib/Lex/Pragma.cpp
+++ b/clang/lib/Lex/Pragma.cpp
@@ -42,6 +42,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Timer.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -1038,6 +1039,8 @@ struct PragmaDebugHandler : public PragmaHandler {
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
llvm_unreachable("This is an assertion!");
} else if (II->isStr("crash")) {
+ llvm::Timer T("crash", "pragma crash");
+ llvm::TimeRegion R(&T);
if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash)
LLVM_BUILTIN_TRAP;
} else if (II->isStr("parser_crash")) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 63d8d7506d03..04a7038d6754 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13909,7 +13909,12 @@ void Sema::ActOnStmtExprError() {
}
ExprResult Sema::ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
- SourceLocation RPLoc) { // "({..})"
+ SourceLocation RPLoc) {
+ return BuildStmtExpr(LPLoc, SubStmt, RPLoc, getTemplateDepth(S));
+}
+
+ExprResult Sema::BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc, unsigned TemplateDepth) {
assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
@@ -13938,18 +13943,10 @@ ExprResult Sema::ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
}
}
- bool IsDependentContext = false;
- if (S)
- IsDependentContext = S->getTemplateParamParent() != nullptr;
- else
- // FIXME: This is not correct when substituting inside a templated
- // context that isn't a DeclContext (such as a variable template).
- IsDependentContext = CurContext->isDependentContext();
-
// FIXME: Check that expression type is complete/non-abstract; statement
// expressions are not lvalues.
Expr *ResStmtExpr =
- new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc, IsDependentContext);
+ new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc, TemplateDepth);
if (StmtExprMayBindToTemp)
return MaybeBindToTemporary(ResStmtExpr);
return ResStmtExpr;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 705abdb4ce72..e97171b6334e 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -6802,7 +6802,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
Context, SubStmt, SourceLocation(), SourceLocation());
Expr *E = new (Context)
StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), SourceLocation(),
- CurContext->isDependentContext());
+ /*FIXME TemplateDepth=*/0);
return MaybeCreateExprWithCleanups(E);
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index ad4ea2d2593d..4f577a3cf748 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -46,6 +46,48 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
}
+unsigned Sema::getTemplateDepth(Scope *S) const {
+ unsigned Depth = 0;
+
+ // Each template parameter scope represents one level of template parameter
+ // depth.
+ for (Scope *TempParamScope = S->getTemplateParamParent();
+ TempParamScope && !Depth;
+ TempParamScope = TempParamScope->getParent()->getTemplateParamParent()) {
+ ++Depth;
+ }
+
+ // Note that there are template parameters with the given depth.
+ auto ParamsAtDepth = [&](unsigned D) { Depth = std::max(Depth, D + 1); };
+
+ // Look for parameters of an enclosing generic lambda. We don't create a
+ // template parameter scope for these.
+ for (FunctionScopeInfo *FSI : getFunctionScopes()) {
+ if (auto *LSI = dyn_cast<LambdaScopeInfo>(FSI)) {
+ if (!LSI->TemplateParams.empty()) {
+ ParamsAtDepth(LSI->AutoTemplateParameterDepth);
+ break;
+ }
+ if (LSI->GLTemplateParameterList) {
+ ParamsAtDepth(LSI->GLTemplateParameterList->getDepth());
+ break;
+ }
+ }
+ }
+
+ // Look for parameters of an enclosing terse function template. We don't
+ // create a template parameter scope for these either.
+ for (const InventedTemplateParameterInfo &Info :
+ getInventedParameterInfos()) {
+ if (!Info.TemplateParams.empty()) {
+ ParamsAtDepth(Info.AutoTemplateParameterDepth);
+ break;
+ }
+ }
+
+ return Depth;
+}
+
/// \brief Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
/// returns null.
@@ -2173,9 +2215,15 @@ private:
// constructor.
ExprResult NewDefArg;
if (OldParam->hasDefaultArg()) {
- NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args);
- if (NewDefArg.isInvalid())
- return nullptr;
+ // We don't care what the value is (we won't use it); just create a
+ // placeholder to indicate there is a default argument.
+ QualType ParamTy = NewDI->getType();
+ NewDefArg = new (SemaRef.Context)
+ OpaqueValueExpr(OldParam->getDefaultArg()->getBeginLoc(),
+ ParamTy.getNonLValueExprType(SemaRef.Context),
+ ParamTy->isLValueReferenceType() ? VK_LValue :
+ ParamTy->isRValueReferenceType() ? VK_XValue :
+ VK_RValue);
}
ParmVarDecl *NewParam = ParmVarDecl::Create(SemaRef.Context, DC,
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 568f5404dc0b..b5d2ab1f31f2 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -922,6 +922,10 @@ namespace {
this->Entity = Entity;
}
+ unsigned TransformTemplateDepth(unsigned Depth) {
+ return TemplateArgs.getNewDepth(Depth);
+ }
+
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
SourceRange PatternRange,
ArrayRef<UnexpandedParameterPack> Unexpanded,
@@ -2162,7 +2166,7 @@ namespace {
// The deduced type itself.
TemplateTypeParmDecl *VisitTemplateTypeParmType(
const TemplateTypeParmType *T) {
- if (!T->getDecl()->isImplicit())
+ if (!T->getDecl() || !T->getDecl()->isImplicit())
return nullptr;
return T->getDecl();
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 0892f966ac2e..805fe6684205 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -212,6 +212,14 @@ public:
return T.isNull();
}
+ /// Transform a template parameter depth level.
+ ///
+ /// During a transformation that transforms template parameters, this maps
+ /// an old template parameter depth to a new depth.
+ unsigned TransformTemplateDepth(unsigned Depth) {
+ return Depth;
+ }
+
/// Determine whether the given call argument should be dropped, e.g.,
/// because it is a default argument.
///
@@ -2527,8 +2535,9 @@ public:
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildStmtExpr(SourceLocation LParenLoc, Stmt *SubStmt,
- SourceLocation RParenLoc) {
- return getSema().ActOnStmtExpr(nullptr, LParenLoc, SubStmt, RParenLoc);
+ SourceLocation RParenLoc, unsigned TemplateDepth) {
+ return getSema().BuildStmtExpr(LParenLoc, SubStmt, RParenLoc,
+ TemplateDepth);
}
/// Build a new __builtin_choose_expr expression.
@@ -10345,16 +10354,18 @@ TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
return ExprError();
}
- if (!getDerived().AlwaysRebuild() &&
+ unsigned OldDepth = E->getTemplateDepth();
+ unsigned NewDepth = getDerived().TransformTemplateDepth(OldDepth);
+
+ if (!getDerived().AlwaysRebuild() && OldDepth == NewDepth &&
SubStmt.get() == E->getSubStmt()) {
// Calling this an 'error' is unintuitive, but it does the right thing.
SemaRef.ActOnStmtExprError();
return SemaRef.MaybeBindToTemporary(E);
}
- return getDerived().RebuildStmtExpr(E->getLParenLoc(),
- SubStmt.get(),
- E->getRParenLoc());
+ return getDerived().RebuildStmtExpr(E->getLParenLoc(), SubStmt.get(),
+ E->getRParenLoc(), NewDepth);
}
template<typename Derived>
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index b7000a6956d9..e3eea3c6f860 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2867,7 +2867,8 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) {
return LocalOffset + M.GlobalBitOffset;
}
-static bool isSameTemplateParameterList(const TemplateParameterList *X,
+static bool isSameTemplateParameterList(const ASTContext &C,
+ const TemplateParameterList *X,
const TemplateParameterList *Y);
/// Determine whether two template parameters are similar enough
@@ -2879,7 +2880,32 @@ static bool isSameTemplateParameter(const NamedDecl *X,
if (const auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
const auto *TY = cast<TemplateTypeParmDecl>(Y);
- return TX->isParameterPack() == TY->isParameterPack();
+ if (TX->isParameterPack() != TY->isParameterPack())
+ return false;
+ if (TX->hasTypeConstraint() != TY->hasTypeConstraint())
+ return false;
+ if (TX->hasTypeConstraint()) {
+ const TypeConstraint *TXTC = TX->getTypeConstraint();
+ const TypeConstraint *TYTC = TY->getTypeConstraint();
+ if (TXTC->getNamedConcept() != TYTC->getNamedConcept())
+ return false;
+ if (TXTC->hasExplicitTemplateArgs() != TYTC->hasExplicitTemplateArgs())
+ return false;
+ if (TXTC->hasExplicitTemplateArgs()) {
+ const auto *TXTCArgs = TXTC->getTemplateArgsAsWritten();
+ const auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
+ if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
+ return false;
+ llvm::FoldingSetNodeID XID, YID;
+ for (const auto &ArgLoc : TXTCArgs->arguments())
+ ArgLoc.getArgument().Profile(XID, X->getASTContext());
+ for (const auto &ArgLoc : TYTCArgs->arguments())
+ ArgLoc.getArgument().Profile(YID, Y->getASTContext());
+ if (XID != YID)
+ return false;
+ }
+ }
+ return true;
}
if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
@@ -2891,7 +2917,8 @@ static bool isSameTemplateParameter(const NamedDecl *X,
const auto *TX = cast<TemplateTemplateParmDecl>(X);
const auto *TY = cast<TemplateTemplateParmDecl>(Y);
return TX->isParameterPack() == TY->isParameterPack() &&
- isSameTemplateParameterList(TX->getTemplateParameters(),
+ isSameTemplateParameterList(TX->getASTContext(),
+ TX->getTemplateParameters(),
TY->getTemplateParameters());
}
@@ -2944,7 +2971,8 @@ static bool isSameQualifier(const NestedNameSpecifier *X,
/// Determine whether two template parameter lists are similar enough
/// that they may be used in declarations of the same template.
-static bool isSameTemplateParameterList(const TemplateParameterList *X,
+static bool isSameTemplateParameterList(const ASTContext &C,
+ const TemplateParameterList *X,
const TemplateParameterList *Y) {
if (X->size() != Y->size())
return false;
@@ -2953,6 +2981,18 @@ static bool isSameTemplateParameterList(const TemplateParameterList *X,
if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
return false;
+ const Expr *XRC = X->getRequiresClause();
+ const Expr *YRC = Y->getRequiresClause();
+ if (!XRC != !YRC)
+ return false;
+ if (XRC) {
+ llvm::FoldingSetNodeID XRCID, YRCID;
+ XRC->Profile(XRCID, C, /*Canonical=*/true);
+ YRC->Profile(YRCID, C, /*Canonical=*/true);
+ if (XRCID != YRCID)
+ return false;
+ }
+
return true;
}
@@ -2989,7 +3029,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A,
return true;
}
-/// Determine whether the two declarations refer to the same entity.
+/// Determine whether the two declarations refer to the same entity.pr
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
@@ -3064,6 +3104,19 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
}
ASTContext &C = FuncX->getASTContext();
+
+ const Expr *XRC = FuncX->getTrailingRequiresClause();
+ const Expr *YRC = FuncY->getTrailingRequiresClause();
+ if (!XRC != !YRC)
+ return false;
+ if (XRC) {
+ llvm::FoldingSetNodeID XRCID, YRCID;
+ XRC->Profile(XRCID, C, /*Canonical=*/true);
+ YRC->Profile(YRCID, C, /*Canonical=*/true);
+ if (XRCID != YRCID)
+ return false;
+ }
+
auto GetTypeAsWritten = [](const FunctionDecl *FD) {
// Map to the first declaration that we've already merged into this one.
// The TSI of redeclarations might not match (due to calling conventions
@@ -3087,6 +3140,7 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
return true;
return false;
}
+
return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() &&
hasSameOverloadableAttrs(FuncX, FuncY);
}
@@ -3126,7 +3180,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
const auto *TemplateY = cast<TemplateDecl>(Y);
return isSameEntity(TemplateX->getTemplatedDecl(),
TemplateY->getTemplatedDecl()) &&
- isSameTemplateParameterList(TemplateX->getTemplateParameters(),
+ isSameTemplateParameterList(TemplateX->getASTContext(),
+ TemplateX->getTemplateParameters(),
TemplateY->getTemplateParameters());
}
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 5dd0ef9d43c3..c38b3ad18467 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -754,6 +754,7 @@ void ASTStmtReader::VisitConceptSpecializationExpr(
E->TemplateKWLoc = Record.readSourceLocation();
E->ConceptName = Record.readDeclarationNameInfo();
E->NamedConcept = readDeclAs<ConceptDecl>();
+ E->FoundDecl = Record.readDeclAs<NamedDecl>();
E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
llvm::SmallVector<TemplateArgument, 4> Args;
for (unsigned I = 0; I < NumTemplateArgs; ++I)
@@ -1190,6 +1191,7 @@ void ASTStmtReader::VisitStmtExpr(StmtExpr *E) {
E->setLParenLoc(readSourceLocation());
E->setRParenLoc(readSourceLocation());
E->setSubStmt(cast_or_null<CompoundStmt>(Record.readSubStmt()));
+ E->StmtExprBits.TemplateDepth = Record.readInt();
}
void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) {
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 1b118c257a4c..8519a4df019d 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -429,6 +429,7 @@ void ASTStmtWriter::VisitConceptSpecializationExpr(
Record.AddSourceLocation(E->getTemplateKWLoc());
Record.AddDeclarationNameInfo(E->getConceptNameInfo());
Record.AddDeclRef(E->getNamedConcept());
+ Record.AddDeclRef(E->getFoundDecl());
Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten());
for (const TemplateArgument &Arg : TemplateArgs)
Record.AddTemplateArgument(Arg);
@@ -1068,6 +1069,7 @@ void ASTStmtWriter::VisitStmtExpr(StmtExpr *E) {
Record.AddStmt(E->getSubStmt());
Record.AddSourceLocation(E->getLParenLoc());
Record.AddSourceLocation(E->getRParenLoc());
+ Record.push_back(E->getTemplateDepth());
Code = serialization::EXPR_STMT;
}