diff options
-rw-r--r-- | clang/include/clang/AST/Expr.h | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 27 | ||||
-rw-r--r-- | clang/test/SemaTemplate/instantiate-init.cpp | 28 |
4 files changed, 75 insertions, 4 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 369249bf5d7..ff16480c059 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2443,6 +2443,8 @@ public: return cast_or_null<Expr>(Exprs[Init]); } + Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); } + SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 0dbefe1dd09..41a7fe653d8 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2523,9 +2523,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, return; } - // FIXME: Need to handle dependent types and expressions here. - - // We will treat direct-initialization as a copy-initialization: + // We will represent direct-initialization similarly to copy-initialization: // int x(1); -as-> int x = 1; // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); // @@ -2535,6 +2533,24 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, // exactly form was it (like the CodeGen) can handle both cases without // special case code. + // If either the declaration has a dependent type or if any of the expressions + // is type-dependent, we represent the initialization via a ParenListExpr for + // later use during template instantiation. + if (VDecl->getType()->isDependentType() || + Expr::hasAnyTypeDependentArguments((Expr **)Exprs.get(), Exprs.size())) { + // Let clients know that initialization was done with a direct initializer. + VDecl->setCXXDirectInitializer(true); + + // Store the initialization expressions as a ParenListExpr. + unsigned NumExprs = Exprs.size(); + VDecl->setInit(Context, + new (Context) ParenListExpr(Context, LParenLoc, + (Expr **)Exprs.release(), + NumExprs, RParenLoc)); + return; + } + + // C++ 8.5p11: // The form of initialization (using parentheses or '=') is generally // insignificant, but does matter when the entity being initialized has a diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index bd25c8fb157..71fb36892b6 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -15,6 +15,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/Support/Compiler.h" using namespace clang; @@ -153,7 +154,31 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { = SemaRef.SubstExpr(D->getInit(), TemplateArgs); if (Init.isInvalid()) Var->setInvalidDecl(); - else + else if (ParenListExpr *PLE = dyn_cast<ParenListExpr>((Expr *)Init.get())) { + // FIXME: We're faking all of the comma locations, which is suboptimal. + // Do we even need these comma locations? + llvm::SmallVector<SourceLocation, 4> FakeCommaLocs; + if (PLE->getNumExprs() > 0) { + FakeCommaLocs.reserve(PLE->getNumExprs() - 1); + for (unsigned I = 0, N = PLE->getNumExprs() - 1; I != N; ++I) { + Expr *E = PLE->getExpr(I)->Retain(); + FakeCommaLocs.push_back( + SemaRef.PP.getLocForEndOfToken(E->getLocEnd())); + } + } + + // Add the direct initializer to the declaration. + SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var), + PLE->getLParenLoc(), + Sema::MultiExprArg(SemaRef, + (void**)PLE->getExprs(), + PLE->getNumExprs()), + FakeCommaLocs.data(), + PLE->getRParenLoc()); + + // When Init is destroyed, it will destroy the instantiated ParenListExpr; + // we've explicitly retained all of its subexpressions already. + } else SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), move(Init), D->hasCXXDirectInitializer()); } else if (!Var->isStaticDataMember() || Var->isOutOfLine()) diff --git a/clang/test/SemaTemplate/instantiate-init.cpp b/clang/test/SemaTemplate/instantiate-init.cpp new file mode 100644 index 00000000000..870b27537fc --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-init.cpp @@ -0,0 +1,28 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct X0 { // expected-note 4{{candidate}} + X0(int*, float*); // expected-note 4{{candidate}} +}; + +template<typename T, typename U> +X0 f0(T t, U u) { + X0 x0(t, u); // expected-error{{no matching}} + return X0(t, u); // expected-error{{no matching}} +} + +void test_f0(int *ip, float *fp, double *dp) { + f0(ip, fp); + f0(ip, dp); // expected-note{{instantiation}} +} + +template<typename Ret, typename T, typename U> +Ret f1(Ret *retty, T t, U u) { + Ret r0(t, u); // expected-error{{no matching}} + return Ret(t, u); // expected-error{{no matching}} +} + +void test_f1(X0 *x0, int *ip, float *fp, double *dp) { + f1(x0, ip, fp); + f1(x0, ip, dp); // expected-note{{instantiation}} +} + |