diff options
-rw-r--r-- | include/clang/AST/Stmt.h | 1 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 106 | ||||
-rw-r--r-- | test/SemaObjCXX/blocks.mm | 10 |
3 files changed, 79 insertions, 38 deletions
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 48871f5325..f68f78bd44 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -143,6 +143,7 @@ protected: friend class DeclRefExpr; // computeDependence friend class InitListExpr; // ctor friend class DesignatedInitExpr; // ctor + friend class BlockDeclRefExpr; // ctor friend class ASTStmtReader; // deserialization friend class CXXNewExpr; // ctor friend class DependentScopeDeclRefExpr; // ctor diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 9dc790256e..c45fe3497d 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -145,11 +145,14 @@ std::size_t ExplicitTemplateArgumentList::sizeFor( return sizeFor(Info.size()); } -void DeclRefExpr::computeDependence() { - ExprBits.TypeDependent = false; - ExprBits.ValueDependent = false; +/// \brief Compute the type- and value-dependence of a declaration reference +/// based on the declaration being referenced. +static void computeDeclRefDependence(NamedDecl *D, QualType T, + bool &TypeDependent, + bool &ValueDependent) { + TypeDependent = false; + ValueDependent = false; - NamedDecl *D = getDecl(); // (TD) C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: @@ -158,60 +161,84 @@ void DeclRefExpr::computeDependence() { // // (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, - if (getType()->isDependentType()) { - ExprBits.TypeDependent = true; - ExprBits.ValueDependent = true; + if (T->isDependentType()) { + TypeDependent = true; + ValueDependent = true; + return; } + // (TD) - a conversion-function-id that specifies a dependent type - else if (D->getDeclName().getNameKind() - == DeclarationName::CXXConversionFunctionName && + if (D->getDeclName().getNameKind() + == DeclarationName::CXXConversionFunctionName && D->getDeclName().getCXXNameType()->isDependentType()) { - ExprBits.TypeDependent = true; - ExprBits.ValueDependent = true; - } - // (TD) - a template-id that is dependent, - else if (hasExplicitTemplateArgs() && - TemplateSpecializationType::anyDependentTemplateArguments( - getTemplateArgs(), - getNumTemplateArgs())) { - ExprBits.TypeDependent = true; - ExprBits.ValueDependent = true; + TypeDependent = true; + ValueDependent = true; + return; } // (VD) - the name of a non-type template parameter, - else if (isa<NonTypeTemplateParmDecl>(D)) - ExprBits.ValueDependent = true; + if (isa<NonTypeTemplateParmDecl>(D)) { + ValueDependent = true; + return; + } + // (VD) - a constant with integral or enumeration type and is // initialized with an expression that is value-dependent. - else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + if (VarDecl *Var = dyn_cast<VarDecl>(D)) { if (Var->getType()->isIntegralOrEnumerationType() && Var->getType().getCVRQualifiers() == Qualifiers::Const) { if (const Expr *Init = Var->getAnyInitializer()) if (Init->isValueDependent()) - ExprBits.ValueDependent = true; + ValueDependent = true; } + // (VD) - FIXME: Missing from the standard: // - a member function or a static data member of the current // instantiation else if (Var->isStaticDataMember() && Var->getDeclContext()->isDependentContext()) - ExprBits.ValueDependent = true; - } + ValueDependent = true; + + return; + } + // (VD) - FIXME: Missing from the standard: // - a member function or a static data member of the current // instantiation - else if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) - ExprBits.ValueDependent = true; - // (TD) - a nested-name-specifier or a qualified-id that names a - // member of an unknown specialization. - // (handled by DependentScopeDeclRefExpr) - - // Determine whether this expression contains any unexpanded parameter - // packs. + if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) { + ValueDependent = true; + return; + } +} + +void DeclRefExpr::computeDependence() { + bool TypeDependent = false; + bool ValueDependent = false; + computeDeclRefDependence(getDecl(), getType(), TypeDependent, ValueDependent); + + // (TD) 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: + if (!TypeDependent && !ValueDependent && + hasExplicitTemplateArgs() && + TemplateSpecializationType::anyDependentTemplateArguments( + getTemplateArgs(), + getNumTemplateArgs())) { + TypeDependent = true; + ValueDependent = true; + } + + ExprBits.TypeDependent = TypeDependent; + ExprBits.ValueDependent = ValueDependent; + // Is the declaration a parameter pack? - if (D->isParameterPack()) + if (getDecl()->isParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; } @@ -2935,13 +2962,16 @@ Stmt::child_iterator ObjCMessageExpr::child_end() { BlockDeclRefExpr::BlockDeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK, SourceLocation l, bool ByRef, bool constAdded, Stmt *copyConstructorVal) - : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, - (!t.isNull() && t->isDependentType()), false, + : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, false, false, d->isParameterPack()), D(d), Loc(l), IsByRef(ByRef), ConstQualAdded(constAdded), CopyConstructorVal(copyConstructorVal) { - // FIXME: Compute type/value dependence. + bool TypeDependent = false; + bool ValueDependent = false; + computeDeclRefDependence(D, getType(), TypeDependent, ValueDependent); + ExprBits.TypeDependent = TypeDependent; + ExprBits.ValueDependent = ValueDependent; } Stmt::child_iterator BlockExpr::child_begin() { return child_iterator(); } diff --git a/test/SemaObjCXX/blocks.mm b/test/SemaObjCXX/blocks.mm index d3f4d9823c..0108ed4f90 100644 --- a/test/SemaObjCXX/blocks.mm +++ b/test/SemaObjCXX/blocks.mm @@ -94,3 +94,13 @@ namespace N2 { } template void test2<2>(); } + +// Handle value-dependent block declaration references. +namespace N3 { + template<int N> struct X { }; + + template<int N> + void f() { + X<N> xN = ^() { return X<N>(); }(); + } +} |