mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-17 16:31:02 +00:00
An expression should only contain an unexpanded parameter pack if it
lexically contains a mention of the pack. Systematically distinguish between syntactic and semantic references to packs, especially when propagating dependence from a type into an expression. We should consult the type-as-written when computing syntactic dependence and should consult the semantic type when computing semantic dependence. Fixes #54402.
This commit is contained in:
parent
a7c0b7504c
commit
f1b0a4fc54
@ -30,7 +30,8 @@ class UnaryExprOrTypeTraitExpr;
|
||||
class ArraySubscriptExpr;
|
||||
class MatrixSubscriptExpr;
|
||||
class CompoundLiteralExpr;
|
||||
class CastExpr;
|
||||
class ImplicitCastExpr;
|
||||
class ExplicitCastExpr;
|
||||
class BinaryOperator;
|
||||
class ConditionalOperator;
|
||||
class BinaryConditionalOperator;
|
||||
@ -70,6 +71,7 @@ class CXXPseudoDestructorExpr;
|
||||
class OverloadExpr;
|
||||
class DependentScopeDeclRefExpr;
|
||||
class CXXConstructExpr;
|
||||
class CXXTemporaryObjectExpr;
|
||||
class CXXDefaultInitExpr;
|
||||
class CXXDefaultArgExpr;
|
||||
class LambdaExpr;
|
||||
@ -114,7 +116,8 @@ ExprDependence computeDependence(UnaryExprOrTypeTraitExpr *E);
|
||||
ExprDependence computeDependence(ArraySubscriptExpr *E);
|
||||
ExprDependence computeDependence(MatrixSubscriptExpr *E);
|
||||
ExprDependence computeDependence(CompoundLiteralExpr *E);
|
||||
ExprDependence computeDependence(CastExpr *E);
|
||||
ExprDependence computeDependence(ImplicitCastExpr *E);
|
||||
ExprDependence computeDependence(ExplicitCastExpr *E);
|
||||
ExprDependence computeDependence(BinaryOperator *E);
|
||||
ExprDependence computeDependence(ConditionalOperator *E);
|
||||
ExprDependence computeDependence(BinaryConditionalOperator *E);
|
||||
@ -156,6 +159,7 @@ ExprDependence computeDependence(OverloadExpr *E, bool KnownDependent,
|
||||
bool KnownContainsUnexpandedParameterPack);
|
||||
ExprDependence computeDependence(DependentScopeDeclRefExpr *E);
|
||||
ExprDependence computeDependence(CXXConstructExpr *E);
|
||||
ExprDependence computeDependence(CXXTemporaryObjectExpr *E);
|
||||
ExprDependence computeDependence(CXXDefaultInitExpr *E);
|
||||
ExprDependence computeDependence(CXXDefaultArgExpr *E);
|
||||
ExprDependence computeDependence(LambdaExpr *E,
|
||||
|
@ -130,6 +130,14 @@ public:
|
||||
|
||||
// Dependence that is propagated syntactically, regardless of semantics.
|
||||
Syntactic = UnexpandedPack | Instantiation | Error,
|
||||
// Dependence that is propagated semantically, even in cases where the
|
||||
// type doesn't syntactically appear. This currently excludes only
|
||||
// UnexpandedPack. Even though Instantiation dependence is also notionally
|
||||
// syntactic, we also want to propagate it semantically because anything
|
||||
// that semantically depends on an instantiation-dependent entity should
|
||||
// always be instantiated when that instantiation-dependent entity is.
|
||||
Semantic =
|
||||
Instantiation | Type | Value | Dependent | Error | VariablyModified,
|
||||
|
||||
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/VariablyModified)
|
||||
};
|
||||
@ -175,6 +183,14 @@ public:
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Extract the semantic portions of this type's dependence that apply even
|
||||
/// to uses where the type does not appear syntactically.
|
||||
Dependence semantic() {
|
||||
Dependence Result = *this;
|
||||
Result.V &= Semantic;
|
||||
return Result;
|
||||
}
|
||||
|
||||
TypeDependence type() const {
|
||||
return translate(V, UnexpandedPack, TypeDependence::UnexpandedPack) |
|
||||
translate(V, Instantiation, TypeDependence::Instantiation) |
|
||||
@ -231,7 +247,10 @@ private:
|
||||
inline ExprDependence toExprDependence(TemplateArgumentDependence TA) {
|
||||
return Dependence(TA).expr();
|
||||
}
|
||||
inline ExprDependence toExprDependence(TypeDependence D) {
|
||||
inline ExprDependence toExprDependenceForImpliedType(TypeDependence D) {
|
||||
return Dependence(D).semantic().expr();
|
||||
}
|
||||
inline ExprDependence toExprDependenceAsWritten(TypeDependence D) {
|
||||
return Dependence(D).expr();
|
||||
}
|
||||
// Note: it's often necessary to strip `Dependent` from qualifiers.
|
||||
@ -269,6 +288,9 @@ inline TypeDependence toTypeDependence(TemplateArgumentDependence D) {
|
||||
inline TypeDependence toSyntacticDependence(TypeDependence D) {
|
||||
return Dependence(D).syntactic().type();
|
||||
}
|
||||
inline TypeDependence toSemanticDependence(TypeDependence D) {
|
||||
return Dependence(D).semantic().type();
|
||||
}
|
||||
|
||||
inline NestedNameSpecifierDependence
|
||||
toNestedNameSpecifierDependendence(TypeDependence D) {
|
||||
|
@ -3497,7 +3497,6 @@ protected:
|
||||
CastExprBits.BasePathSize = BasePathSize;
|
||||
assert((CastExprBits.BasePathSize == BasePathSize) &&
|
||||
"BasePathSize overflow!");
|
||||
setDependence(computeDependence(this));
|
||||
assert(CastConsistency());
|
||||
CastExprBits.HasFPFeatures = HasFPFeatures;
|
||||
}
|
||||
@ -3631,6 +3630,7 @@ class ImplicitCastExpr final
|
||||
ExprValueKind VK)
|
||||
: CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength,
|
||||
FPO.requiresTrailingStorage()) {
|
||||
setDependence(computeDependence(this));
|
||||
if (hasStoredFPFeatures())
|
||||
*getTrailingFPFeatures() = FPO;
|
||||
}
|
||||
@ -3708,7 +3708,9 @@ protected:
|
||||
CastKind kind, Expr *op, unsigned PathSize,
|
||||
bool HasFPFeatures, TypeSourceInfo *writtenTy)
|
||||
: CastExpr(SC, exprTy, VK, kind, op, PathSize, HasFPFeatures),
|
||||
TInfo(writtenTy) {}
|
||||
TInfo(writtenTy) {
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
/// Construct an empty explicit cast.
|
||||
ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize,
|
||||
|
@ -26,7 +26,7 @@ ExprDependence clang::computeDependence(FullExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(OpaqueValueExpr *E) {
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
if (auto *S = E->getSourceExpr())
|
||||
D |= S->getDependence();
|
||||
assert(!(D & ExprDependence::UnexpandedPack));
|
||||
@ -39,8 +39,10 @@ ExprDependence clang::computeDependence(ParenExpr *E) {
|
||||
|
||||
ExprDependence clang::computeDependence(UnaryOperator *E,
|
||||
const ASTContext &Ctx) {
|
||||
ExprDependence Dep = toExprDependence(E->getType()->getDependence()) |
|
||||
E->getSubExpr()->getDependence();
|
||||
ExprDependence Dep =
|
||||
// FIXME: Do we need to look at the type?
|
||||
toExprDependenceForImpliedType(E->getType()->getDependence()) |
|
||||
E->getSubExpr()->getDependence();
|
||||
|
||||
// C++ [temp.dep.constexpr]p5:
|
||||
// An expression of the form & qualified-id where the qualified-id names a
|
||||
@ -77,7 +79,7 @@ ExprDependence clang::computeDependence(UnaryExprOrTypeTraitExpr *E) {
|
||||
// Value-dependent if the argument is type-dependent.
|
||||
if (E->isArgumentType())
|
||||
return turnTypeToValueDependence(
|
||||
toExprDependence(E->getArgumentType()->getDependence()));
|
||||
toExprDependenceAsWritten(E->getArgumentType()->getDependence()));
|
||||
|
||||
auto ArgDeps = E->getArgumentExpr()->getDependence();
|
||||
auto Deps = ArgDeps & ~ExprDependence::TypeValue;
|
||||
@ -120,21 +122,36 @@ ExprDependence clang::computeDependence(MatrixSubscriptExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CompoundLiteralExpr *E) {
|
||||
return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence()) |
|
||||
return toExprDependenceAsWritten(
|
||||
E->getTypeSourceInfo()->getType()->getDependence()) |
|
||||
toExprDependenceForImpliedType(E->getType()->getDependence()) |
|
||||
turnTypeToValueDependence(E->getInitializer()->getDependence());
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CastExpr *E) {
|
||||
ExprDependence clang::computeDependence(ImplicitCastExpr *E) {
|
||||
// We model implicit conversions as combining the dependence of their
|
||||
// subexpression, apart from its type, with the semantic portion of the
|
||||
// target type.
|
||||
ExprDependence D =
|
||||
toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
if (auto *S = E->getSubExpr())
|
||||
D |= S->getDependence() & ~ExprDependence::Type;
|
||||
return D;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(ExplicitCastExpr *E) {
|
||||
// Cast expressions are type-dependent if the type is
|
||||
// dependent (C++ [temp.dep.expr]p3).
|
||||
// Cast expressions are value-dependent if the type is
|
||||
// dependent or if the subexpression is value-dependent.
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
if (E->getStmtClass() == Stmt::ImplicitCastExprClass) {
|
||||
// An implicit cast expression doesn't (lexically) contain an
|
||||
// unexpanded pack, even if its target type does.
|
||||
D &= ~ExprDependence::UnexpandedPack;
|
||||
}
|
||||
//
|
||||
// Note that we also need to consider the dependence of the actual type here,
|
||||
// because when the type as written is a deduced type, that type is not
|
||||
// dependent, but it may be deduced as a dependent type.
|
||||
ExprDependence D =
|
||||
toExprDependenceAsWritten(
|
||||
cast<ExplicitCastExpr>(E)->getTypeAsWritten()->getDependence()) |
|
||||
toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
if (auto *S = E->getSubExpr())
|
||||
D |= S->getDependence() & ~ExprDependence::Type;
|
||||
return D;
|
||||
@ -158,7 +175,7 @@ ExprDependence clang::computeDependence(BinaryConditionalOperator *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
// Propagate dependence of the result.
|
||||
if (const auto *CompoundExprResult =
|
||||
dyn_cast_or_null<ValueStmt>(E->getSubStmt()->getStmtExprResult()))
|
||||
@ -174,7 +191,8 @@ ExprDependence clang::computeDependence(StmtExpr *E, unsigned TemplateDepth) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(ConvertVectorExpr *E) {
|
||||
auto D = toExprDependence(E->getType()->getDependence()) |
|
||||
auto D = toExprDependenceAsWritten(
|
||||
E->getTypeSourceInfo()->getType()->getDependence()) |
|
||||
E->getSrcExpr()->getDependence();
|
||||
if (!E->getType()->isDependentType())
|
||||
D &= ~ExprDependence::Type;
|
||||
@ -206,14 +224,14 @@ ExprDependence clang::computeDependence(ParenListExpr *P) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(VAArgExpr *E) {
|
||||
auto D =
|
||||
toExprDependence(E->getWrittenTypeInfo()->getType()->getDependence()) |
|
||||
(E->getSubExpr()->getDependence() & ~ExprDependence::Type);
|
||||
auto D = toExprDependenceAsWritten(
|
||||
E->getWrittenTypeInfo()->getType()->getDependence()) |
|
||||
(E->getSubExpr()->getDependence() & ~ExprDependence::Type);
|
||||
return D & ~ExprDependence::Value;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(NoInitExpr *E) {
|
||||
return toExprDependence(E->getType()->getDependence()) &
|
||||
return toExprDependenceForImpliedType(E->getType()->getDependence()) &
|
||||
(ExprDependence::Instantiation | ExprDependence::Error);
|
||||
}
|
||||
|
||||
@ -226,7 +244,7 @@ ExprDependence clang::computeDependence(ArrayInitLoopExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(ImplicitValueInitExpr *E) {
|
||||
return toExprDependence(E->getType()->getDependence()) &
|
||||
return toExprDependenceForImpliedType(E->getType()->getDependence()) &
|
||||
ExprDependence::Instantiation;
|
||||
}
|
||||
|
||||
@ -235,14 +253,16 @@ ExprDependence clang::computeDependence(ExtVectorElementExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(BlockExpr *E) {
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
if (E->getBlockDecl()->isDependentContext())
|
||||
D |= ExprDependence::Instantiation;
|
||||
return D & ~ExprDependence::UnexpandedPack;
|
||||
return D;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(AsTypeExpr *E) {
|
||||
auto D = toExprDependence(E->getType()->getDependence()) |
|
||||
// FIXME: AsTypeExpr doesn't store the type as written. Assume the expression
|
||||
// type has identical sugar for now, so is a type-as-written.
|
||||
auto D = toExprDependenceAsWritten(E->getType()->getDependence()) |
|
||||
E->getSrcExpr()->getDependence();
|
||||
if (!E->getType()->isDependentType())
|
||||
D &= ~ExprDependence::Type;
|
||||
@ -255,15 +275,14 @@ ExprDependence clang::computeDependence(CXXRewrittenBinaryOperator *E) {
|
||||
|
||||
ExprDependence clang::computeDependence(CXXStdInitializerListExpr *E) {
|
||||
auto D = turnTypeToValueDependence(E->getSubExpr()->getDependence());
|
||||
D |= toExprDependence(E->getType()->getDependence()) &
|
||||
(ExprDependence::Type | ExprDependence::Error);
|
||||
D |= toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
return D;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CXXTypeidExpr *E) {
|
||||
auto D = ExprDependence::None;
|
||||
if (E->isTypeOperand())
|
||||
D = toExprDependence(
|
||||
D = toExprDependenceAsWritten(
|
||||
E->getTypeOperandSourceInfo()->getType()->getDependence());
|
||||
else
|
||||
D = turnTypeToValueDependence(E->getExprOperand()->getDependence());
|
||||
@ -281,7 +300,7 @@ ExprDependence clang::computeDependence(MSPropertySubscriptExpr *E) {
|
||||
|
||||
ExprDependence clang::computeDependence(CXXUuidofExpr *E) {
|
||||
if (E->isTypeOperand())
|
||||
return turnTypeToValueDependence(toExprDependence(
|
||||
return turnTypeToValueDependence(toExprDependenceAsWritten(
|
||||
E->getTypeOperandSourceInfo()->getType()->getDependence()));
|
||||
|
||||
return turnTypeToValueDependence(E->getExprOperand()->getDependence());
|
||||
@ -290,7 +309,7 @@ ExprDependence clang::computeDependence(CXXUuidofExpr *E) {
|
||||
ExprDependence clang::computeDependence(CXXThisExpr *E) {
|
||||
// 'this' is type-dependent if the class type of the enclosing
|
||||
// member function is dependent (C++ [temp.dep.expr]p2)
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
assert(!(D & ExprDependence::UnexpandedPack));
|
||||
return D;
|
||||
}
|
||||
@ -307,8 +326,10 @@ ExprDependence clang::computeDependence(CXXBindTemporaryExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CXXScalarValueInitExpr *E) {
|
||||
return toExprDependence(E->getType()->getDependence()) &
|
||||
~ExprDependence::TypeValue;
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
if (auto *TSI = E->getTypeSourceInfo())
|
||||
D |= toExprDependenceAsWritten(TSI->getType()->getDependence());
|
||||
return D;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CXXDeleteExpr *E) {
|
||||
@ -316,7 +337,7 @@ ExprDependence clang::computeDependence(CXXDeleteExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(ArrayTypeTraitExpr *E) {
|
||||
auto D = toExprDependence(E->getQueriedType()->getDependence());
|
||||
auto D = toExprDependenceAsWritten(E->getQueriedType()->getDependence());
|
||||
if (auto *Dim = E->getDimensionExpression())
|
||||
D |= Dim->getDependence();
|
||||
return turnTypeToValueDependence(D);
|
||||
@ -366,7 +387,7 @@ ExprDependence clang::computeDependence(ObjCBoxedExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(ObjCEncodeExpr *E) {
|
||||
return toExprDependence(E->getEncodedType()->getDependence());
|
||||
return toExprDependenceAsWritten(E->getEncodedType()->getDependence());
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(ObjCIvarRefExpr *E) {
|
||||
@ -377,7 +398,8 @@ ExprDependence clang::computeDependence(ObjCPropertyRefExpr *E) {
|
||||
if (E->isObjectReceiver())
|
||||
return E->getBase()->getDependence() & ~ExprDependence::Type;
|
||||
if (E->isSuperReceiver())
|
||||
return toExprDependence(E->getSuperReceiverType()->getDependence()) &
|
||||
return toExprDependenceForImpliedType(
|
||||
E->getSuperReceiverType()->getDependence()) &
|
||||
~ExprDependence::TypeValue;
|
||||
assert(E->isClassReceiver());
|
||||
return ExprDependence::None;
|
||||
@ -406,19 +428,22 @@ ExprDependence clang::computeDependence(OMPArraySectionExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(OMPArrayShapingExpr *E) {
|
||||
auto D = E->getBase()->getDependence() |
|
||||
toExprDependence(E->getType()->getDependence());
|
||||
auto D = E->getBase()->getDependence();
|
||||
for (Expr *Dim: E->getDimensions())
|
||||
if (Dim)
|
||||
D |= Dim->getDependence();
|
||||
D |= turnValueToTypeDependence(Dim->getDependence());
|
||||
return D;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(OMPIteratorExpr *E) {
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
|
||||
if (auto *VD = cast_or_null<ValueDecl>(E->getIteratorDecl(I)))
|
||||
D |= toExprDependence(VD->getType()->getDependence());
|
||||
if (auto *DD = cast_or_null<DeclaratorDecl>(E->getIteratorDecl(I))) {
|
||||
// If the type is omitted, it's 'int', and is not dependent in any way.
|
||||
if (auto *TSI = DD->getTypeSourceInfo()) {
|
||||
D |= toExprDependenceAsWritten(TSI->getType()->getDependence());
|
||||
}
|
||||
}
|
||||
OMPIteratorExpr::IteratorRange IR = E->getIteratorRange(I);
|
||||
if (Expr *BE = IR.Begin)
|
||||
D |= BE->getDependence();
|
||||
@ -451,7 +476,8 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
|
||||
|
||||
if (Decl->isParameterPack())
|
||||
Deps |= ExprDependence::UnexpandedPack;
|
||||
Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error;
|
||||
Deps |= toExprDependenceForImpliedType(Type->getDependence()) &
|
||||
ExprDependence::Error;
|
||||
|
||||
// C++ [temp.dep.expr]p3:
|
||||
// An id-expression is type-dependent if it contains:
|
||||
@ -547,7 +573,7 @@ ExprDependence clang::computeDependence(RecoveryExpr *E) {
|
||||
// - type-dependent if we don't know the type (fallback to an opaque
|
||||
// dependent type), or the type is known and dependent, or it has
|
||||
// type-dependent subexpressions.
|
||||
auto D = toExprDependence(E->getType()->getDependence()) |
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence()) |
|
||||
ExprDependence::ErrorDependent;
|
||||
// FIXME: remove the type-dependent bit from subexpressions, if the
|
||||
// RecoveryExpr has a non-dependent type.
|
||||
@ -557,12 +583,12 @@ ExprDependence clang::computeDependence(RecoveryExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(SYCLUniqueStableNameExpr *E) {
|
||||
return toExprDependence(E->getTypeSourceInfo()->getType()->getDependence());
|
||||
return toExprDependenceAsWritten(
|
||||
E->getTypeSourceInfo()->getType()->getDependence());
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(PredefinedExpr *E) {
|
||||
return toExprDependence(E->getType()->getDependence()) &
|
||||
~ExprDependence::UnexpandedPack;
|
||||
return toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CallExpr *E,
|
||||
@ -578,8 +604,8 @@ ExprDependence clang::computeDependence(CallExpr *E,
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(OffsetOfExpr *E) {
|
||||
auto D = turnTypeToValueDependence(
|
||||
toExprDependence(E->getTypeSourceInfo()->getType()->getDependence()));
|
||||
auto D = turnTypeToValueDependence(toExprDependenceAsWritten(
|
||||
E->getTypeSourceInfo()->getType()->getDependence()));
|
||||
for (unsigned I = 0, N = E->getNumExpressions(); I < N; ++I)
|
||||
D |= turnTypeToValueDependence(E->getIndexExpr(I)->getDependence());
|
||||
return D;
|
||||
@ -615,7 +641,7 @@ ExprDependence clang::computeDependence(InitListExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(ShuffleVectorExpr *E) {
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
for (auto *C : llvm::makeArrayRef(E->getSubExprs(), E->getNumSubExprs()))
|
||||
D |= C->getDependence();
|
||||
return D;
|
||||
@ -666,7 +692,9 @@ ExprDependence clang::computeDependence(AtomicExpr *A) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CXXNewExpr *E) {
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
auto D = toExprDependenceAsWritten(
|
||||
E->getAllocatedTypeSourceInfo()->getType()->getDependence());
|
||||
D |= toExprDependenceForImpliedType(E->getAllocatedType()->getDependence());
|
||||
auto Size = E->getArraySize();
|
||||
if (Size.hasValue() && *Size)
|
||||
D |= turnTypeToValueDependence((*Size)->getDependence());
|
||||
@ -679,11 +707,11 @@ ExprDependence clang::computeDependence(CXXNewExpr *E) {
|
||||
|
||||
ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) {
|
||||
auto D = E->getBase()->getDependence();
|
||||
if (!E->getDestroyedType().isNull())
|
||||
D |= toExprDependence(E->getDestroyedType()->getDependence());
|
||||
if (auto *TSI = E->getDestroyedTypeInfo())
|
||||
D |= toExprDependenceAsWritten(TSI->getType()->getDependence());
|
||||
if (auto *ST = E->getScopeTypeInfo())
|
||||
D |= turnTypeToValueDependence(
|
||||
toExprDependence(ST->getType()->getDependence()));
|
||||
toExprDependenceAsWritten(ST->getType()->getDependence()));
|
||||
if (auto *Q = E->getQualifier())
|
||||
D |= toExprDependence(Q->getDependence() &
|
||||
~NestedNameSpecifierDependence::Dependent);
|
||||
@ -738,12 +766,20 @@ ExprDependence clang::computeDependence(DependentScopeDeclRefExpr *E) {
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CXXConstructExpr *E) {
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
ExprDependence D =
|
||||
toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
for (auto *A : E->arguments())
|
||||
D |= A->getDependence() & ~ExprDependence::Type;
|
||||
return D;
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CXXTemporaryObjectExpr *E) {
|
||||
CXXConstructExpr *BaseE = E;
|
||||
return toExprDependenceAsWritten(
|
||||
E->getTypeSourceInfo()->getType()->getDependence()) |
|
||||
computeDependence(BaseE);
|
||||
}
|
||||
|
||||
ExprDependence clang::computeDependence(CXXDefaultInitExpr *E) {
|
||||
return E->getExpr()->getDependence();
|
||||
}
|
||||
@ -754,7 +790,7 @@ ExprDependence clang::computeDependence(CXXDefaultArgExpr *E) {
|
||||
|
||||
ExprDependence clang::computeDependence(LambdaExpr *E,
|
||||
bool ContainsUnexpandedParameterPack) {
|
||||
auto D = toExprDependence(E->getType()->getDependence());
|
||||
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
if (ContainsUnexpandedParameterPack)
|
||||
D |= ExprDependence::UnexpandedPack;
|
||||
return D;
|
||||
@ -762,7 +798,8 @@ ExprDependence clang::computeDependence(LambdaExpr *E,
|
||||
|
||||
ExprDependence clang::computeDependence(CXXUnresolvedConstructExpr *E) {
|
||||
auto D = ExprDependence::ValueInstantiation;
|
||||
D |= toExprDependence(E->getType()->getDependence());
|
||||
D |= toExprDependenceAsWritten(E->getTypeAsWritten()->getDependence());
|
||||
D |= toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
for (auto *A : E->arguments())
|
||||
D |= A->getDependence() &
|
||||
(ExprDependence::UnexpandedPack | ExprDependence::Error);
|
||||
@ -797,8 +834,8 @@ ExprDependence clang::computeDependence(CXXFoldExpr *E) {
|
||||
ExprDependence clang::computeDependence(TypeTraitExpr *E) {
|
||||
auto D = ExprDependence::None;
|
||||
for (const auto *A : E->getArgs())
|
||||
D |=
|
||||
toExprDependence(A->getType()->getDependence()) & ~ExprDependence::Type;
|
||||
D |= toExprDependenceAsWritten(A->getType()->getDependence()) &
|
||||
~ExprDependence::Type;
|
||||
return D;
|
||||
}
|
||||
|
||||
@ -845,7 +882,7 @@ ExprDependence clang::computeDependence(ObjCMessageExpr *E) {
|
||||
if (auto *R = E->getInstanceReceiver())
|
||||
D |= R->getDependence();
|
||||
else
|
||||
D |= toExprDependence(E->getType()->getDependence());
|
||||
D |= toExprDependenceForImpliedType(E->getType()->getDependence());
|
||||
for (auto *A : E->arguments())
|
||||
D |= A->getDependence();
|
||||
return D;
|
||||
|
@ -989,7 +989,9 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(
|
||||
Cons, /* Elidable=*/false, Args, HadMultipleCandidates,
|
||||
ListInitialization, StdInitListInitialization, ZeroInitialization,
|
||||
CXXConstructExpr::CK_Complete, ParenOrBraceRange),
|
||||
TSI(TSI) {}
|
||||
TSI(TSI) {
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(EmptyShell Empty,
|
||||
unsigned NumArgs)
|
||||
@ -1075,7 +1077,9 @@ CXXConstructExpr::CXXConstructExpr(
|
||||
TrailingArgs[I] = Args[I];
|
||||
}
|
||||
|
||||
setDependence(computeDependence(this));
|
||||
// CXXTemporaryObjectExpr does this itself after setting its TypeSourceInfo.
|
||||
if (SC == CXXConstructExprClass)
|
||||
setDependence(computeDependence(this));
|
||||
}
|
||||
|
||||
CXXConstructExpr::CXXConstructExpr(StmtClass SC, EmptyShell Empty,
|
||||
|
@ -722,8 +722,7 @@ bool Type::isObjCClassOrClassKindOfType() const {
|
||||
|
||||
ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D, QualType can,
|
||||
ArrayRef<ObjCProtocolDecl *> protocols)
|
||||
: Type(ObjCTypeParam, can,
|
||||
can->getDependence() & ~TypeDependence::UnexpandedPack),
|
||||
: Type(ObjCTypeParam, can, toSemanticDependence(can->getDependence())),
|
||||
OTPDecl(const_cast<ObjCTypeParamDecl *>(D)) {
|
||||
initialize(protocols);
|
||||
}
|
||||
@ -3409,7 +3408,7 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
|
||||
TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D,
|
||||
QualType underlying, QualType can)
|
||||
: Type(tc, can, underlying->getDependence()),
|
||||
: Type(tc, can, toSemanticDependence(underlying->getDependence())),
|
||||
Decl(const_cast<TypedefNameDecl *>(D)) {
|
||||
assert(!isa<TypedefType>(can) && "Invalid canonical type");
|
||||
}
|
||||
@ -3420,7 +3419,7 @@ QualType TypedefType::desugar() const {
|
||||
|
||||
UsingType::UsingType(const UsingShadowDecl *Found, QualType Underlying,
|
||||
QualType Canon)
|
||||
: Type(Using, Canon, Underlying->getDependence()),
|
||||
: Type(Using, Canon, toSemanticDependence(Underlying->getDependence())),
|
||||
Found(const_cast<UsingShadowDecl *>(Found)) {
|
||||
assert(Underlying == getUnderlyingType());
|
||||
}
|
||||
@ -3676,8 +3675,7 @@ TemplateSpecializationType::TemplateSpecializationType(
|
||||
: Type(TemplateSpecialization, Canon.isNull() ? QualType(this, 0) : Canon,
|
||||
(Canon.isNull()
|
||||
? TypeDependence::DependentInstantiation
|
||||
: Canon->getDependence() & ~(TypeDependence::VariablyModified |
|
||||
TypeDependence::UnexpandedPack)) |
|
||||
: toSemanticDependence(Canon->getDependence())) |
|
||||
(toTypeDependence(T.getDependence()) &
|
||||
TypeDependence::UnexpandedPack)),
|
||||
Template(T) {
|
||||
|
@ -294,7 +294,7 @@ namespace tuple_tests {
|
||||
}
|
||||
|
||||
namespace dependent {
|
||||
template<typename T> struct X {
|
||||
template<typename T> struct X { // expected-note 3{{here}}
|
||||
X(T);
|
||||
};
|
||||
template<typename T> int Var(T t) {
|
||||
@ -304,12 +304,26 @@ namespace dependent {
|
||||
template<typename T> int Cast(T t) {
|
||||
return X(X(t)) + 1; // expected-error {{invalid operands}}
|
||||
}
|
||||
template<typename T> int Cast2(T t) {
|
||||
return (X)(X)t + 1; // expected-error {{deduction not allowed}}
|
||||
}
|
||||
template<typename T> int Cast3(T t) {
|
||||
return X{X{t}} + 1; // expected-error {{invalid operands}}
|
||||
}
|
||||
template<typename T> int Cast4(T t) {
|
||||
return (X){(X){t}} + 1; // expected-error 2{{deduction not allowed}}
|
||||
}
|
||||
template<typename T> int New(T t) {
|
||||
return X(new X(t)) + 1; // expected-error {{invalid operands}}
|
||||
};
|
||||
template<typename T> int *New2(T t) {
|
||||
return new X(X(t)) * 2; // expected-error {{invalid operands}}
|
||||
};
|
||||
template int Var(float); // expected-note {{instantiation of}}
|
||||
template int Cast(float); // expected-note {{instantiation of}}
|
||||
template int Cast3(float); // expected-note {{instantiation of}}
|
||||
template int New(float); // expected-note {{instantiation of}}
|
||||
template int *New2(float); // expected-note {{instantiation of}}
|
||||
template<typename T> int operator+(X<T>, int);
|
||||
template int Var(int);
|
||||
template int Cast(int);
|
||||
|
167
clang/test/SemaTemplate/find-unexpanded-packs.cpp
Normal file
167
clang/test/SemaTemplate/find-unexpanded-packs.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
// RUN: %clang_cc1 -verify %s -std=c++17 -Wno-unused
|
||||
|
||||
template<typename ...Ts> void PackInsideTypedefDeclaration() {
|
||||
([] {
|
||||
typedef Ts Type;
|
||||
(void)Type();
|
||||
}(), ...);
|
||||
}
|
||||
template void PackInsideTypedefDeclaration<>();
|
||||
template void PackInsideTypedefDeclaration<int>();
|
||||
template void PackInsideTypedefDeclaration<int, float>();
|
||||
|
||||
template<typename ...Ts> void PackInsideTypedefDeclarationInvalid() {
|
||||
[] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
|
||||
typedef Ts Type;
|
||||
(void)Type();
|
||||
};
|
||||
|
||||
([] {
|
||||
typedef Ts Type;
|
||||
// A reference to a typedef containing an unexpanded pack does not
|
||||
// itself contain an unexpanded pack.
|
||||
f(Type()...); // expected-error {{does not contain any unexpanded}}
|
||||
}, ...);
|
||||
}
|
||||
|
||||
|
||||
template<typename ...Ts> void PackInsideAliasDeclaration() {
|
||||
([] {
|
||||
using Type = Ts;
|
||||
(void)Type();
|
||||
}(), ...);
|
||||
}
|
||||
template void PackInsideAliasDeclaration<>();
|
||||
template void PackInsideAliasDeclaration<int>();
|
||||
template void PackInsideAliasDeclaration<int, float>();
|
||||
|
||||
template<typename ...Ts> void PackInsideAliasDeclarationInvalid() {
|
||||
[] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
|
||||
using Type = Ts;
|
||||
(void)Type();
|
||||
};
|
||||
([] {
|
||||
using Type = Ts;
|
||||
// A reference to an alias containing an unexpanded pack does not
|
||||
// itself contain an unexpanded pack.
|
||||
f(Type()...); // expected-error {{does not contain any unexpanded}}
|
||||
}, ...);
|
||||
}
|
||||
|
||||
|
||||
template<typename ...Ts> void PackInsideUsingDeclaration() {
|
||||
([] {
|
||||
struct A {
|
||||
using Type = Ts;
|
||||
};
|
||||
struct B : A {
|
||||
using typename A::Type;
|
||||
};
|
||||
(void)typename B::Type();
|
||||
}(), ...);
|
||||
}
|
||||
template void PackInsideUsingDeclaration<>();
|
||||
template void PackInsideUsingDeclaration<int>();
|
||||
template void PackInsideUsingDeclaration<int, float>();
|
||||
|
||||
template<typename ...Ts> void PackInsideUsingDeclarationInvalid() {
|
||||
([] {
|
||||
struct A {
|
||||
using Type = Ts;
|
||||
};
|
||||
struct B : A {
|
||||
using typename A::Type...; // expected-error {{does not contain any unexpanded}}
|
||||
};
|
||||
}(), ...);
|
||||
}
|
||||
|
||||
|
||||
template<typename ...Ts> void PackInsideVarDeclaration() {
|
||||
([] {
|
||||
Ts ts;
|
||||
(void)ts;
|
||||
}, ...);
|
||||
}
|
||||
template void PackInsideVarDeclaration<>();
|
||||
template void PackInsideVarDeclaration<int>();
|
||||
template void PackInsideVarDeclaration<int, float>();
|
||||
|
||||
template<typename ...Ts> void PackInsideVarDeclarationInvalid() {
|
||||
[] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
|
||||
Ts ts;
|
||||
(void)ts;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<typename ...Ts> void PackInsideFunctionDeclaration() {
|
||||
([] {
|
||||
Ts ts(Ts);
|
||||
ts({});
|
||||
}, ...);
|
||||
}
|
||||
template void PackInsideFunctionDeclaration<>();
|
||||
template void PackInsideFunctionDeclaration<int>();
|
||||
template void PackInsideFunctionDeclaration<int, float>();
|
||||
|
||||
template<typename ...Ts> void PackInsideFunctionDeclarationInvalid() {
|
||||
[] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
|
||||
Ts ts(Ts);
|
||||
ts({});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<typename ...Ts> void PackInsideLocalClass() {
|
||||
([] {
|
||||
class Local {
|
||||
Ts ts;
|
||||
};
|
||||
Local l;
|
||||
}, ...);
|
||||
}
|
||||
template void PackInsideLocalClass<>();
|
||||
template void PackInsideLocalClass<int>();
|
||||
template void PackInsideLocalClass<int, float>();
|
||||
|
||||
template<typename ...Ts> void PackInsideLocalClassInvalid() {
|
||||
[] { // expected-error {{contains unexpanded parameter pack 'Ts'}}
|
||||
class Local {
|
||||
Ts ts;
|
||||
};
|
||||
Local l;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T> using Int = int;
|
||||
struct AClass {};
|
||||
template<typename T> using Class = AClass;
|
||||
template<typename ...Ts> void HiddenPack() {
|
||||
(Int<Ts>(), ...);
|
||||
(Int<Ts>{}, ...);
|
||||
(Class<Ts>(), ...);
|
||||
(Class<Ts>{}, ...);
|
||||
|
||||
([] {
|
||||
Int<Ts>();
|
||||
}, ...);
|
||||
([] {
|
||||
Int<Ts>{};
|
||||
}, ...);
|
||||
([] {
|
||||
Class<Ts>();
|
||||
}, ...);
|
||||
([] {
|
||||
Class<Ts>{};
|
||||
}, ...);
|
||||
}
|
||||
template void HiddenPack<>();
|
||||
template void HiddenPack<int>();
|
||||
template void HiddenPack<int, float>();
|
||||
|
||||
template<typename ...Ts> void HiddenPackInvalid() {
|
||||
Int<Ts>(); // expected-error {{unexpanded}}
|
||||
Int<Ts>{}; // expected-error {{unexpanded}}
|
||||
Class<Ts>(); // expected-error {{unexpanded}}
|
||||
Class<Ts>{}; // expected-error {{unexpanded}}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user