]> granicus.if.org Git - clang/commitdiff
Fix PR9488: 'auto' type substitution can fail (for instance, if it creates a referenc...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 17 Mar 2011 16:11:59 +0000 (16:11 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 17 Mar 2011 16:11:59 +0000 (16:11 +0000)
Also fix an issue where type source information for the resulting type was being lost.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127811 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaTemplateDeduction.cpp
test/SemaCXX/auto-subst-failure.cpp [new file with mode: 0644]

index 394a57ae258f2c6ce31ea0fe5866a715f543391b..043722b29c945a649724b3e673c0efa2326227a2 100644 (file)
@@ -3879,7 +3879,8 @@ public:
                           FunctionDecl *&Specialization,
                           sema::TemplateDeductionInfo &Info);
 
-  bool DeduceAutoType(QualType AutoType, Expr *Initializer, QualType &Result);
+  bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *Initializer,
+                      TypeSourceInfo *&Result);
 
   FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
                                                    FunctionTemplateDecl *FT2,
index a10b32513d3b8dbf7544ce35089f411f6034de17..540c4e0bf0ac7658f0a6ea38acd5331498f224fd 100644 (file)
@@ -4664,15 +4664,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
 
   // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
   if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
-    QualType DeducedType;
-    if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
+    TypeSourceInfo *DeducedType = 0;
+    if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
       Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
         << VDecl->getDeclName() << VDecl->getType() << Init->getType()
         << Init->getSourceRange();
+    if (!DeducedType) {
       RealDecl->setInvalidDecl();
       return;
     }
-    VDecl->setType(DeducedType);
+    VDecl->setTypeSourceInfo(DeducedType);
+    VDecl->setType(DeducedType->getType());
 
     // If this is a redeclaration, check that the type we just deduced matches
     // the previously declared type.
index 04c21bc47ca4f948e86fb1cbc60cec9ac0d50b5c..430f9c80521b6dac67cd555f506569da4ae261ae 100644 (file)
@@ -6137,15 +6137,17 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
     }
 
     Expr *Init = Exprs.get()[0];
-    QualType DeducedType;
-    if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
+    TypeSourceInfo *DeducedType = 0;
+    if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType))
       Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
         << VDecl->getDeclName() << VDecl->getType() << Init->getType()
         << Init->getSourceRange();
+    if (!DeducedType) {
       RealDecl->setInvalidDecl();
       return;
     }
-    VDecl->setType(DeducedType);
+    VDecl->setTypeSourceInfo(DeducedType);
+    VDecl->setType(DeducedType->getType());
 
     // If this is a redeclaration, check that the type we just deduced matches
     // the previously declared type.
index 9955b0378bd1547352fc27a0a4c770f237228be7..8ceeff953647a49f42060817c07b7f1a1f2312ea 100644 (file)
@@ -848,16 +848,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
                             diag::err_auto_new_ctor_multiple_expressions)
                        << AllocType << TypeRange);
     }
-    QualType DeducedType;
-    if (!DeduceAutoType(AllocType, ConstructorArgs.get()[0], DeducedType))
+    TypeSourceInfo *DeducedType = 0;
+    if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType))
       return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
                        << AllocType
                        << ConstructorArgs.get()[0]->getType()
                        << TypeRange
                        << ConstructorArgs.get()[0]->getSourceRange());
+    if (!DeducedType)
+      return ExprError();
 
-    AllocType = DeducedType;
-    AllocTypeInfo = Context.getTrivialTypeSourceInfo(AllocType, StartLoc);
+    AllocTypeInfo = DeducedType;
+    AllocType = AllocTypeInfo->getType();
   }
   
   // Per C++0x [expr.new]p5, the type being constructed may be a
index c6b4d96d02e2783805cfd3d1cd1dc2a2933ef887..202a736f3fdefa5c7ad53928e5950ebc765af428 100644 (file)
@@ -3003,11 +3003,14 @@ namespace {
 ///
 /// \param Result if type deduction was successful, this will be set to the
 /// deduced type. This may still contain undeduced autos if the type is
-/// dependent.
+/// dependent. This will be set to null if deduction succeeded, but auto
+/// substitution failed; the appropriate diagnostic will already have been
+/// produced in that case.
 ///
 /// \returns true if deduction succeeded, false if it failed.
 bool
-Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
+Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init,
+                     TypeSourceInfo *&Result) {
   if (Init->isTypeDependent()) {
     Result = Type;
     return true;
@@ -3025,8 +3028,10 @@ Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
   FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr,
                                                    Loc);
 
-  QualType FuncParam =
+  TypeSourceInfo *FuncParamInfo =
     SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
+  assert(FuncParamInfo && "substituting template parameter for 'auto' failed");
+  QualType FuncParam = FuncParamInfo->getType();
 
   // Deduce type of TemplParam in Func(Init)
   llvm::SmallVector<DeducedTemplateArgument, 1> Deduced;
diff --git a/test/SemaCXX/auto-subst-failure.cpp b/test/SemaCXX/auto-subst-failure.cpp
new file mode 100644 (file)
index 0000000..442c7e8
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+
+void f() {
+  auto a = f(); // expected-error {{variable has incomplete type 'void'}}
+  auto &b = f(); // expected-error {{cannot form a reference to 'void'}}
+  auto *c = f(); // expected-error {{incompatible initializer of type 'void'}}
+
+  auto d(f()); // expected-error {{variable has incomplete type 'void'}}
+  auto &&e(f()); // expected-error {{cannot form a reference to 'void'}}
+  auto *g(f()); // expected-error {{incompatible initializer of type 'void'}}
+
+  (void)new auto(f()); // expected-error {{allocation of incomplete type 'void'}}
+  (void)new auto&(f()); // expected-error {{cannot form a reference to 'void'}}
+  (void)new auto*(f()); // expected-error {{incompatible constructor argument of type 'void'}}
+}