From: John McCall Date: Fri, 9 Apr 2010 17:38:44 +0000 (+0000) Subject: Instantiate default argument expressions even if their associated parameter X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6cd3b9fb8a29bb70fff01719bdde238723d67c10;p=clang Instantiate default argument expressions even if their associated parameter type isn't dependent. Fixes rdar://problem/7838962. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100871 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 65c5793be8..3250870d63 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3638,6 +3638,11 @@ public: const MultiLevelTemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity); + TypeSourceInfo *SubstFunctionDeclType(TypeSourceInfo *T, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, + DeclarationName Entity); + OwningExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index d21862b71e..6895364abf 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -959,6 +959,56 @@ QualType Sema::SubstType(QualType T, return Instantiator.TransformType(T); } +static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) { + if (T->getType()->isDependentType()) + return true; + + TypeLoc TL = T->getTypeLoc(); + if (!isa(TL)) + return false; + + FunctionProtoTypeLoc FP = cast(TL); + for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) { + ParmVarDecl *P = FP.getArg(I); + + // TODO: currently we always rebuild expressions. When we + // properly get lazier about this, we should use the same + // logic to avoid rebuilding prototypes here. + if (P->hasInit()) + return true; + } + + return false; +} + +/// A form of SubstType intended specifically for instantiating the +/// type of a FunctionDecl. Its purpose is solely to force the +/// instantiation of default-argument expressions. +TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, + const MultiLevelTemplateArgumentList &Args, + SourceLocation Loc, + DeclarationName Entity) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + + if (!NeedsInstantiationAsFunctionType(T)) + return T; + + TemplateInstantiator Instantiator(*this, Args, Loc, Entity); + + TypeLocBuilder TLB; + + TypeLoc TL = T->getTypeLoc(); + TLB.reserve(TL.getFullDataSize()); + + QualType Result = Instantiator.TransformType(TLB, TL, QualType()); + if (Result.isNull()) + return 0; + + return TLB.getTypeSourceInfo(Context, Result); +} + /// \brief Perform substitution on the base class specifiers of the /// given class template specialization. /// diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 1ac854c770..82270451cb 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1826,9 +1826,10 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, TypeSourceInfo *OldTInfo = D->getTypeSourceInfo(); assert(OldTInfo && "substituting function without type source info"); assert(Params.empty() && "parameter vector is non-empty at start"); - TypeSourceInfo *NewTInfo = SemaRef.SubstType(OldTInfo, TemplateArgs, - D->getTypeSpecStartLoc(), - D->getDeclName()); + TypeSourceInfo *NewTInfo + = SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs, + D->getTypeSpecStartLoc(), + D->getDeclName()); if (!NewTInfo) return 0; diff --git a/test/CXX/temp/temp.spec/temp.inst/p11.cpp b/test/CXX/temp/temp.spec/temp.inst/p11.cpp new file mode 100644 index 0000000000..d375beb10a --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.inst/p11.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify -emit-llvm-only %s + +// rdar://problem/7838962 +namespace test0 { + template unsigned f0() { + return T::MaxSize; // expected-error {{'int' cannot be used prior to '::'}} + }; + template class A { + void Allocate(unsigned Alignment + = f0()) // expected-note {{in instantiation}} + {} + }; + void f1(A x) { x.Allocate(); } + +}