aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp138
1 files changed, 93 insertions, 45 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp b/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp
index 2333993dbeb4..4026fdc76fd6 100644
--- a/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp
+++ b/contrib/llvm-project/clang/lib/AST/ComputeDependence.cpp
@@ -37,9 +37,39 @@ ExprDependence clang::computeDependence(ParenExpr *E) {
return E->getSubExpr()->getDependence();
}
-ExprDependence clang::computeDependence(UnaryOperator *E) {
- return toExprDependence(E->getType()->getDependence()) |
- E->getSubExpr()->getDependence();
+ExprDependence clang::computeDependence(UnaryOperator *E,
+ const ASTContext &Ctx) {
+ ExprDependence Dep = toExprDependence(E->getType()->getDependence()) |
+ E->getSubExpr()->getDependence();
+
+ // C++ [temp.dep.constexpr]p5:
+ // An expression of the form & qualified-id where the qualified-id names a
+ // dependent member of the current instantiation is value-dependent. An
+ // expression of the form & cast-expression is also value-dependent if
+ // evaluating cast-expression as a core constant expression succeeds and
+ // the result of the evaluation refers to a templated entity that is an
+ // object with static or thread storage duration or a member function.
+ //
+ // What this amounts to is: constant-evaluate the operand and check whether it
+ // refers to a templated entity other than a variable with local storage.
+ if (Ctx.getLangOpts().CPlusPlus && E->getOpcode() == UO_AddrOf &&
+ !(Dep & ExprDependence::Value)) {
+ Expr::EvalResult Result;
+ SmallVector<PartialDiagnosticAt, 8> Diag;
+ Result.Diag = &Diag;
+ // FIXME: This doesn't enforce the C++98 constant expression rules.
+ if (E->getSubExpr()->EvaluateAsConstantExpr(Result, Ctx) && Diag.empty() &&
+ Result.Val.isLValue()) {
+ auto *VD = Result.Val.getLValueBase().dyn_cast<const ValueDecl *>();
+ if (VD && VD->isTemplated()) {
+ auto *VarD = dyn_cast<VarDecl>(VD);
+ if (!VarD || !VarD->hasLocalStorage())
+ Dep |= ExprDependence::Value;
+ }
+ }
+ }
+
+ return Dep;
}
ExprDependence clang::computeDependence(UnaryExprOrTypeTraitExpr *E) {
@@ -423,22 +453,21 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
Deps |= ExprDependence::UnexpandedPack;
Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error;
- // (TD) C++ [temp.dep.expr]p3:
+ // C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
- //
- // and
- //
- // (VD) C++ [temp.dep.constexpr]p2:
- // An identifier is value-dependent if it is:
- // (TD) - an identifier that was declared with dependent type
- // (VD) - a name declared with a dependent type,
+ // - an identifier associated by name lookup with one or more declarations
+ // declared with a dependent type
+ //
+ // [The "or more" case is not modeled as a DeclRefExpr. There are a bunch
+ // more bullets here that we handle by treating the declaration as having a
+ // dependent type if they involve a placeholder type that can't be deduced.]
if (Type->isDependentType())
return Deps | ExprDependence::TypeValueInstantiation;
else if (Type->isInstantiationDependentType())
Deps |= ExprDependence::Instantiation;
- // (TD) - a conversion-function-id that specifies a dependent type
+ // - a conversion-function-id that specifies a dependent type
if (Decl->getDeclName().getNameKind() ==
DeclarationName::CXXConversionFunctionName) {
QualType T = Decl->getDeclName().getCXXNameType();
@@ -449,48 +478,65 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
Deps |= ExprDependence::Instantiation;
}
- // (VD) - the name of a non-type template parameter,
+ // - a template-id that is dependent,
+ // - a nested-name-specifier or a qualified-id that names a member of an
+ // unknown specialization
+ // [These are not modeled as DeclRefExprs.]
+
+ // or if it names a dependent member of the current instantiation that is a
+ // static data member of type "array of unknown bound of T" for some T
+ // [handled below].
+
+ // C++ [temp.dep.constexpr]p2:
+ // An id-expression is value-dependent if:
+
+ // - it is type-dependent [handled above]
+
+ // - it is the name of a non-type template parameter,
if (isa<NonTypeTemplateParmDecl>(Decl))
return Deps | ExprDependence::ValueInstantiation;
- // (VD) - a constant with integral or enumeration type and is
- // initialized with an expression that is value-dependent.
- // (VD) - a constant with literal type and is initialized with an
- // expression that is value-dependent [C++11].
- // (VD) - FIXME: Missing from the standard:
- // - an entity with reference type and is initialized with an
- // expression that is value-dependent [C++11]
- if (VarDecl *Var = dyn_cast<VarDecl>(Decl)) {
- if ((Ctx.getLangOpts().CPlusPlus11
- ? Var->getType()->isLiteralType(Ctx)
- : Var->getType()->isIntegralOrEnumerationType()) &&
- (Var->getType().isConstQualified() ||
- Var->getType()->isReferenceType())) {
- if (const Expr *Init = Var->getAnyInitializer())
- if (Init->isValueDependent()) {
+ // - it names a potentially-constant variable that is initialized with an
+ // expression that is value-dependent
+ if (const auto *Var = dyn_cast<VarDecl>(Decl)) {
+ if (Var->mightBeUsableInConstantExpressions(Ctx)) {
+ if (const Expr *Init = Var->getAnyInitializer()) {
+ if (Init->isValueDependent())
Deps |= ExprDependence::ValueInstantiation;
- }
+ if (Init->containsErrors())
+ Deps |= ExprDependence::Error;
+ }
}
- // (VD) - FIXME: Missing from the standard:
- // - a member function or a static data member of the current
- // instantiation
+ // - it names a static data member that is a dependent member of the
+ // current instantiation and is not initialized in a member-declarator,
if (Var->isStaticDataMember() &&
- Var->getDeclContext()->isDependentContext()) {
- Deps |= ExprDependence::ValueInstantiation;
- TypeSourceInfo *TInfo = Var->getFirstDecl()->getTypeSourceInfo();
- if (TInfo->getType()->isIncompleteArrayType())
- Deps |= ExprDependence::Type;
+ Var->getDeclContext()->isDependentContext() &&
+ !Var->getFirstDecl()->hasInit()) {
+ const VarDecl *First = Var->getFirstDecl();
+ TypeSourceInfo *TInfo = First->getTypeSourceInfo();
+ if (TInfo->getType()->isIncompleteArrayType()) {
+ Deps |= ExprDependence::TypeValueInstantiation;
+ } else if (!First->hasInit()) {
+ Deps |= ExprDependence::ValueInstantiation;
+ }
}
return Deps;
}
- // (VD) - FIXME: Missing from the standard:
- // - a member function or a static data member of the current
- // instantiation
- if (isa<CXXMethodDecl>(Decl) && Decl->getDeclContext()->isDependentContext())
- Deps |= ExprDependence::ValueInstantiation;
+ // - it names a static member function that is a dependent member of the
+ // current instantiation
+ //
+ // FIXME: It's unclear that the restriction to static members here has any
+ // effect: any use of a non-static member function name requires either
+ // forming a pointer-to-member or providing an object parameter, either of
+ // which makes the overall expression value-dependent.
+ if (auto *MD = dyn_cast<CXXMethodDecl>(Decl)) {
+ if (MD->isStatic() && Decl->getDeclContext()->isDependentContext())
+ Deps |= ExprDependence::ValueInstantiation;
+ }
+
return Deps;
}
@@ -502,7 +548,7 @@ ExprDependence clang::computeDependence(RecoveryExpr *E) {
// dependent type), or the type is known and dependent, or it has
// type-dependent subexpressions.
auto D = toExprDependence(E->getType()->getDependence()) |
- ExprDependence::ValueInstantiation | ExprDependence::Error;
+ ExprDependence::ErrorDependent;
// FIXME: remove the type-dependent bit from subexpressions, if the
// RecoveryExpr has a non-dependent type.
for (auto *S : E->subExpressions())
@@ -694,6 +740,10 @@ ExprDependence clang::computeDependence(CXXConstructExpr *E) {
return D;
}
+ExprDependence clang::computeDependence(CXXDefaultInitExpr *E) {
+ return E->getExpr()->getDependence();
+}
+
ExprDependence clang::computeDependence(LambdaExpr *E,
bool ContainsUnexpandedParameterPack) {
auto D = toExprDependence(E->getType()->getDependence());
@@ -705,8 +755,6 @@ ExprDependence clang::computeDependence(LambdaExpr *E,
ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) {
auto D = ExprDependence::ValueInstantiation;
D |= toExprDependence(E->getType()->getDependence());
- if (E->getType()->getContainedDeducedType())
- D |= ExprDependence::Type;
for (auto *A : E->arguments())
D |= A->getDependence() &
(ExprDependence::UnexpandedPack | ExprDependence::Error);