r180789 - Don't treat a non-deduced 'auto' type as being type-dependent. Instead, there

Richard Smith richard-llvm at metafoo.co.uk
Tue Apr 30 06:56:42 PDT 2013


Author: rsmith
Date: Tue Apr 30 08:56:41 2013
New Revision: 180789

URL: http://llvm.org/viewvc/llvm-project?rev=180789&view=rev
Log:
Don't treat a non-deduced 'auto' type as being type-dependent. Instead, there
are now two distinct canonical 'AutoType's: one is the undeduced 'auto'
placeholder type, and the other is a deduced-but-dependent type. All
deduced-to-a-non-dependent-type cases are still non-canonical.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/AST/TypeNodes.def
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/CodeGen/CGRTTI.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/SemaCXX/condition.cpp
    cfe/trunk/test/SemaCXX/cxx11-crashes.cpp
    cfe/trunk/test/SemaCXX/for-range-unused.cpp
    cfe/trunk/test/SemaTemplate/dependent-names.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Apr 30 08:56:41 2013
@@ -1100,7 +1100,8 @@ public:
                                  UnaryTransformType::UTTKind UKind) const;
 
   /// \brief C++11 deduced auto type.
-  QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto) const;
+  QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
+                       bool IsDependent = false) const;
 
   /// \brief C++11 deduction pattern for 'auto' type.
   QualType getAutoDeductType() const;

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Apr 30 08:56:41 2013
@@ -1619,6 +1619,10 @@ public:
     return TypeBits.InstantiationDependent;
   }
 
+  /// \brief Determine whether this type is an undeduced type, meaning that
+  /// it somehow involves a C++11 'auto' type which has not yet been deduced.
+  bool isUndeducedType() const;
+
   /// \brief Whether this type is a variably-modified type (C99 6.7.5).
   bool isVariablyModifiedType() const { return TypeBits.VariablyModified; }
 
@@ -3554,17 +3558,17 @@ public:
 
 /// \brief Represents a C++11 auto or C++1y decltype(auto) type.
 ///
-/// These types are usually a placeholder for a deduced type. However, within
-/// templates and before the initializer is attached, there is no deduced type
-/// and an auto type is type-dependent and canonical.
+/// These types are usually a placeholder for a deduced type. However, before
+/// the initializer is attached, or if the initializer is type-dependent, there
+/// is no deduced type and an auto type is canonical. In the latter case, it is
+/// also a dependent type.
 class AutoType : public Type, public llvm::FoldingSetNode {
-  AutoType(QualType DeducedType, bool IsDecltypeAuto)
+  AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent)
     : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
-           /*Dependent=*/DeducedType.isNull(),
-           /*InstantiationDependent=*/DeducedType.isNull(),
+           /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
            /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
-    assert((DeducedType.isNull() || !DeducedType->isDependentType()) &&
-           "deduced a dependent type for auto");
+    assert((DeducedType.isNull() || !IsDependent) &&
+           "auto deduced to dependent type");
     AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;
   }
 
@@ -3573,24 +3577,27 @@ class AutoType : public Type, public llv
 public:
   bool isDecltypeAuto() const { return AutoTypeBits.IsDecltypeAuto; }
 
-  bool isSugared() const { return isDeduced(); }
+  bool isSugared() const { return !isCanonicalUnqualified(); }
   QualType desugar() const { return getCanonicalTypeInternal(); }
 
+  /// \brief Get the type deduced for this auto type, or null if it's either
+  /// not been deduced or was deduced to a dependent type.
   QualType getDeducedType() const {
-    return isDeduced() ? getCanonicalTypeInternal() : QualType();
+    return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType();
   }
   bool isDeduced() const {
-    return !isDependentType();
+    return !isCanonicalUnqualified() || isDependentType();
   }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getDeducedType(), isDecltypeAuto());
+    Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType());
   }
 
-  static void Profile(llvm::FoldingSetNodeID &ID,
-                      QualType Deduced, bool IsDecltypeAuto) {
+  static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
+                      bool IsDecltypeAuto, bool IsDependent) {
     ID.AddPointer(Deduced.getAsOpaquePtr());
     ID.AddBoolean(IsDecltypeAuto);
+    ID.AddBoolean(IsDependent);
   }
 
   static bool classof(const Type *T) {
@@ -5033,6 +5040,11 @@ inline bool Type::isBooleanType() const
   return false;
 }
 
+inline bool Type::isUndeducedType() const {
+  const AutoType *AT = getContainedAutoType();
+  return AT && !AT->isDeduced();
+}
+
 /// \brief Determines whether this is a type for which one can define
 /// an overloaded operator.
 inline bool Type::isOverloadableType() const {

Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Tue Apr 30 08:56:41 2013
@@ -94,7 +94,7 @@ DEPENDENT_TYPE(TemplateTypeParm, Type)
 NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
 DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
 NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
-NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Auto, Type)
+TYPE(Auto, Type)
 DEPENDENT_TYPE(InjectedClassName, Type)
 DEPENDENT_TYPE(DependentName, Type)
 DEPENDENT_TYPE(DependentTemplateSpecialization, Type)

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Apr 30 08:56:41 2013
@@ -1400,6 +1400,7 @@ public:
                                      MultiTemplateParamsArg TemplateParamLists);
   // Returns true if the variable declaration is a redeclaration
   bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
+  void CheckVariableDeclarationType(VarDecl *NewVD);
   void CheckCompleteVariableDeclaration(VarDecl *var);
   void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
   void ActOnStartFunctionDeclarator();
@@ -5643,6 +5644,7 @@ public:
 
   DeduceAutoResult DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer,
                                   TypeSourceInfo *&Result);
+  QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
   void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
 
   FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Apr 30 08:56:41 2013
@@ -1597,7 +1597,8 @@ ASTContext::getTypeInfoImpl(const Type *
 
   case Type::Auto: {
     const AutoType *A = cast<AutoType>(T);
-    assert(A->isDeduced() && "Cannot request the size of a dependent type");
+    assert(!A->getDeducedType().isNull() &&
+           "cannot request the size of an undeduced or dependent auto type");
     return getTypeInfo(A->getDeducedType().getTypePtr());
   }
 
@@ -3564,18 +3565,20 @@ QualType ASTContext::getUnaryTransformTy
 
 /// getAutoType - We only unique auto types after they've been deduced.
 QualType ASTContext::getAutoType(QualType DeducedType,
-                                 bool IsDecltypeAuto) const {
+                                 bool IsDecltypeAuto,
+                                 bool IsDependent) const {
   void *InsertPos = 0;
   if (!DeducedType.isNull()) {
     // Look in the folding set for an existing type.
     llvm::FoldingSetNodeID ID;
-    AutoType::Profile(ID, DeducedType, IsDecltypeAuto);
+    AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent);
     if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
       return QualType(AT, 0);
   }
 
   AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType,
-                                                     IsDecltypeAuto);
+                                                     IsDecltypeAuto,
+                                                     IsDependent);
   Types.push_back(AT);
   if (InsertPos)
     AutoTypes.InsertNode(AT, InsertPos);
@@ -5387,6 +5390,11 @@ void ASTContext::getObjCEncodingForTypeI
     // FIXME. We should do a better job than gcc.
     return;
 
+  case Type::Auto:
+    // We could see an undeduced auto type here during error recovery.
+    // Just ignore it.
+    return;
+
 #define ABSTRACT_TYPE(KIND, BASE)
 #define TYPE(KIND, BASE)
 #define DEPENDENT_TYPE(KIND, BASE) \
@@ -7028,6 +7036,7 @@ QualType ASTContext::mergeTypes(QualType
 #include "clang/AST/TypeNodes.def"
     llvm_unreachable("Non-canonical and dependent types shouldn't get here");
 
+  case Type::Auto:
   case Type::LValueReference:
   case Type::RValueReference:
   case Type::MemberPointer:

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Apr 30 08:56:41 2013
@@ -2105,6 +2105,11 @@ static CachedProperties computeCachedPro
     assert(T->isInstantiationDependentType());
     return CachedProperties(ExternalLinkage, false);
 
+  case Type::Auto:
+    // Give non-deduced 'auto' types external linkage. We should only see them
+    // here in error recovery.
+    return CachedProperties(ExternalLinkage, false);
+
   case Type::Builtin:
     // C++ [basic.link]p8:
     //   A type is said to have linkage if and only if:
@@ -2206,6 +2211,9 @@ static LinkageInfo computeLinkageInfo(co
   case Type::Builtin:
     return LinkageInfo::external();
 
+  case Type::Auto:
+    return LinkageInfo::external();
+
   case Type::Record:
   case Type::Enum:
     return cast<TagType>(T)->getDecl()->getLinkageAndVisibility();

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Tue Apr 30 08:56:41 2013
@@ -776,7 +776,7 @@ void TypePrinter::printUnaryTransformAft
 
 void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) { 
   // If the type has been deduced, do not print 'auto'.
-  if (T->isDeduced()) {
+  if (!T->getDeducedType().isNull()) {
     printBefore(T->getDeducedType(), OS);
   } else {
     OS << (T->isDecltypeAuto() ? "decltype(auto)" : "auto");
@@ -785,7 +785,7 @@ void TypePrinter::printAutoBefore(const
 }
 void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) { 
   // If the type has been deduced, do not print 'auto'.
-  if (T->isDeduced())
+  if (!T->getDeducedType().isNull())
     printAfter(T->getDeducedType(), OS);
 }
 

Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Tue Apr 30 08:56:41 2013
@@ -412,6 +412,9 @@ void RTTIBuilder::BuildVTablePointer(con
   case Type::RValueReference:
     llvm_unreachable("References shouldn't get here");
 
+  case Type::Auto:
+    llvm_unreachable("Undeduced auto type shouldn't get here");
+
   case Type::Builtin:
   // GCC treats vector and complex types as fundamental types.
   case Type::Vector:
@@ -619,6 +622,9 @@ llvm::Constant *RTTIBuilder::BuildTypeIn
   case Type::RValueReference:
     llvm_unreachable("References shouldn't get here");
 
+  case Type::Auto:
+    llvm_unreachable("Undeduced auto type shouldn't get here");
+
   case Type::ConstantArray:
   case Type::IncompleteArray:
   case Type::VariableArray:

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Apr 30 08:56:41 2013
@@ -91,6 +91,9 @@ TypeEvaluationKind CodeGenFunction::getE
 #include "clang/AST/TypeNodes.def"
       llvm_unreachable("non-canonical or dependent type in IR-generation");
 
+    case Type::Auto:
+      llvm_unreachable("undeduced auto type in IR-generation");
+
     // Various scalar types.
     case Type::Builtin:
     case Type::Pointer:

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Tue Apr 30 08:56:41 2013
@@ -392,6 +392,8 @@ llvm::Type *CodeGenTypes::ConvertType(Qu
     }
     break;
   }
+  case Type::Auto:
+    llvm_unreachable("Unexpected undeduced auto type!");
   case Type::Complex: {
     llvm::Type *EltTy = ConvertType(cast<ComplexType>(Ty)->getElementType());
     ResultType = llvm::StructType::get(EltTy, EltTy, NULL);

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Apr 30 08:56:41 2013
@@ -1456,6 +1456,8 @@ bool Parser::ParseCXXCondition(ExprResul
   if (!InitExpr.isInvalid())
     Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization,
                                  DS.containsPlaceholderType());
+  else
+    Actions.ActOnInitializerError(DeclOut);
 
   // FIXME: Build a reference to this declaration? Convert it to bool?
   // (This is currently handled by Sema).

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Apr 30 08:56:41 2013
@@ -2798,8 +2798,7 @@ void Sema::MergeVarDeclTypes(VarDecl *Ne
 
   QualType MergedT;
   if (getLangOpts().CPlusPlus) {
-    AutoType *AT = New->getType()->getContainedAutoType();
-    if (AT && !AT->isDeduced()) {
+    if (New->getType()->isUndeducedType()) {
       // We don't know what the new type is until the initializer is attached.
       return;
     } else if (Context.hasSameType(New->getType(), Old->getType())) {
@@ -5142,27 +5141,18 @@ static bool mayConflictWithNonVisibleExt
   return ND->isExternC();
 }
 
-/// \brief Perform semantic checking on a newly-created variable
-/// declaration.
-///
-/// This routine performs all of the type-checking required for a
-/// variable declaration once it has been built. It is used both to
-/// check variables after they have been parsed and their declarators
-/// have been translated into a declaration, and to check variables
-/// that have been instantiated from a template.
-///
-/// Sets NewVD->isInvalidDecl() if an error was encountered.
-///
-/// Returns true if the variable declaration is a redeclaration.
-bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
-                                    LookupResult &Previous) {
+void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
   // If the decl is already known invalid, don't check it.
   if (NewVD->isInvalidDecl())
-    return false;
+    return;
 
   TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo();
   QualType T = TInfo->getType();
 
+  // Defer checking an 'auto' type until its initializer is attached.
+  if (T->isUndeducedType())
+    return;
+
   if (T->isObjCObjectType()) {
     Diag(NewVD->getLocation(), diag::err_statically_allocated_object)
       << FixItHint::CreateInsertion(NewVD->getLocation(), "*");
@@ -5177,7 +5167,7 @@ bool Sema::CheckVariableDeclaration(VarD
   if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) {
     Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl);
     NewVD->setInvalidDecl();
-    return false;
+    return;
   }
 
   // OpenCL v1.2 s6.5 - All program scope variables must be declared in the
@@ -5187,7 +5177,7 @@ bool Sema::CheckVariableDeclaration(VarD
       && !T->isSamplerT()){
     Diag(NewVD->getLocation(), diag::err_opencl_global_invalid_addr_space);
     NewVD->setInvalidDecl();
-    return false;
+    return;
   }
   
   // OpenCL v1.2 s6.8 -- The static qualifier is valid only in program
@@ -5196,7 +5186,7 @@ bool Sema::CheckVariableDeclaration(VarD
       && NewVD->isStaticLocal()) {
     Diag(NewVD->getLocation(), diag::err_static_function_scope);
     NewVD->setInvalidDecl();
-    return false;
+    return;
   }
 
   if (NewVD->hasLocalStorage() && T.isObjCGCWeak()
@@ -5237,7 +5227,7 @@ bool Sema::CheckVariableDeclaration(VarD
         Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage)
         << SizeRange;
       NewVD->setInvalidDecl();
-      return false;
+      return;
     }
 
     if (FixedTInfo == 0) {
@@ -5246,7 +5236,7 @@ bool Sema::CheckVariableDeclaration(VarD
       else
         Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage);
       NewVD->setInvalidDecl();
-      return false;
+      return;
     }
 
     Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size);
@@ -5254,6 +5244,54 @@ bool Sema::CheckVariableDeclaration(VarD
     NewVD->setTypeSourceInfo(FixedTInfo);
   }
 
+  if (T->isVoidType() && NewVD->isThisDeclarationADefinition()) {
+    Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
+      << T;
+    NewVD->setInvalidDecl();
+    return;
+  }
+
+  if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
+    Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
+    NewVD->setInvalidDecl();
+    return;
+  }
+
+  if (isVM && NewVD->hasAttr<BlocksAttr>()) {
+    Diag(NewVD->getLocation(), diag::err_block_on_vm);
+    NewVD->setInvalidDecl();
+    return;
+  }
+
+  if (NewVD->isConstexpr() && !T->isDependentType() &&
+      RequireLiteralType(NewVD->getLocation(), T,
+                         diag::err_constexpr_var_non_literal)) {
+    // Can't perform this check until the type is deduced.
+    NewVD->setInvalidDecl();
+    return;
+  }
+}
+
+/// \brief Perform semantic checking on a newly-created variable
+/// declaration.
+///
+/// This routine performs all of the type-checking required for a
+/// variable declaration once it has been built. It is used both to
+/// check variables after they have been parsed and their declarators
+/// have been translated into a declaration, and to check variables
+/// that have been instantiated from a template.
+///
+/// Sets NewVD->isInvalidDecl() if an error was encountered.
+///
+/// Returns true if the variable declaration is a redeclaration.
+bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
+                                    LookupResult &Previous) {
+  CheckVariableDeclarationType(NewVD);
+
+  // If the decl is already known invalid, don't check it.
+  if (NewVD->isInvalidDecl())
+    return false;
+
   // If we did not find anything by this name, look for a non-visible
   // extern "C" declaration with the same name.
   //
@@ -5292,32 +5330,6 @@ bool Sema::CheckVariableDeclaration(VarD
   // Filter out any non-conflicting previous declarations.
   filterNonConflictingPreviousDecls(Context, NewVD, Previous);
 
-  if (T->isVoidType() && NewVD->isThisDeclarationADefinition()) {
-    Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type)
-      << T;
-    NewVD->setInvalidDecl();
-    return false;
-  }
-
-  if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) {
-    Diag(NewVD->getLocation(), diag::err_block_on_nonlocal);
-    NewVD->setInvalidDecl();
-    return false;
-  }
-
-  if (isVM && NewVD->hasAttr<BlocksAttr>()) {
-    Diag(NewVD->getLocation(), diag::err_block_on_vm);
-    NewVD->setInvalidDecl();
-    return false;
-  }
-
-  if (NewVD->isConstexpr() && !T->isDependentType() &&
-      RequireLiteralType(NewVD->getLocation(), T,
-                         diag::err_constexpr_var_non_literal)) {
-    NewVD->setInvalidDecl();
-    return false;
-  }
-
   if (!Previous.empty()) {
     MergeVarDecl(NewVD, Previous, PreviousWasHidden);
     return true;
@@ -7284,10 +7296,7 @@ void Sema::AddInitializerToDecl(Decl *Re
   ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
 
   // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
-  AutoType *Auto = 0;
-  if (TypeMayContainAuto &&
-      (Auto = VDecl->getType()->getContainedAutoType()) &&
-      !Auto->isDeduced()) {
+  if (TypeMayContainAuto && VDecl->getType()->isUndeducedType()) {
     Expr *DeduceInit = Init;
     // Initializer could be a C++ direct-initializer. Deduction only works if it
     // contains exactly one expression.
@@ -7357,6 +7366,11 @@ void Sema::AddInitializerToDecl(Decl *Re
     // the previously declared type.
     if (VarDecl *Old = VDecl->getPreviousDecl())
       MergeVarDeclTypes(VDecl, Old, /*OldWasHidden*/ false);
+
+    // Check the deduced type is valid for a variable declaration.
+    CheckVariableDeclarationType(VDecl);
+    if (VDecl->isInvalidDecl())
+      return;
   }
 
   if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) {
@@ -8190,8 +8204,8 @@ Sema::BuildDeclaratorGroup(Decl **Group,
         // Don't reissue diagnostics when instantiating a template.
         if (AT && D->isInvalidDecl())
           break;
-        if (AT && AT->isDeduced()) {
-          QualType U = AT->getDeducedType();
+        QualType U = AT ? AT->getDeducedType() : QualType();
+        if (!U.isNull()) {
           CanQualType UCanon = Context.getCanonicalType(U);
           if (Deduced.isNull()) {
             Deduced = U;

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Apr 30 08:56:41 2013
@@ -1118,9 +1118,7 @@ Sema::BuildCXXNew(SourceRange Range, boo
     HaveCompleteInit = true;
 
   // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
-  AutoType *AT = 0;
-  if (TypeMayContainAuto &&
-      (AT = AllocType->getContainedAutoType()) && !AT->isDeduced()) {
+  if (TypeMayContainAuto && AllocType->isUndeducedType()) {
     if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
       return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
                        << AllocType << TypeRange);
@@ -2279,6 +2277,9 @@ Sema::ActOnCXXDelete(SourceLocation Star
 ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
                                         SourceLocation StmtLoc,
                                         bool ConvertToBoolean) {
+  if (ConditionVar->isInvalidDecl())
+    return ExprError();
+
   QualType T = ConditionVar->getType();
 
   // C++ [stmt.select]p2:

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Apr 30 08:56:41 2013
@@ -2087,6 +2087,10 @@ addAssociatedClassesAndNamespaces(Associ
     case Type::Complex:
       break;
 
+    // Non-deduced auto types only get here for error cases.
+    case Type::Auto:
+      break;
+
     // If T is an Objective-C object or interface type, or a pointer to an 
     // object or interface type, the associated namespace is the global
     // namespace.

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Apr 30 08:56:41 2013
@@ -1923,7 +1923,15 @@ Sema::BuildCXXForRangeStmt(SourceLocatio
   StmtResult BeginEndDecl = BeginEnd;
   ExprResult NotEqExpr = Cond, IncrExpr = Inc;
 
-  if (!BeginEndDecl.get() && !RangeVarType->isDependentType()) {
+  if (RangeVarType->isDependentType()) {
+    // The range is implicitly used as a placeholder when it is dependent.
+    RangeVar->setUsed();
+
+    // Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill
+    // them in properly when we instantiate the loop.
+    if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check)
+      LoopVar->setType(SubstAutoType(LoopVar->getType(), Context.DependentTy));
+  } else if (!BeginEndDecl.get()) {
     SourceLocation RangeLoc = RangeVar->getLocation();
 
     const QualType RangeVarNonRefType = RangeVarType.getNonReferenceType();
@@ -2110,9 +2118,6 @@ Sema::BuildCXXForRangeStmt(SourceLocatio
       if (LoopVar->isInvalidDecl())
         NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
     }
-  } else {
-    // The range is implicitly used as a placeholder when it is dependent.
-    RangeVar->setUsed();
   }
 
   // Don't bother to actually allocate the result if we're just trying to

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Apr 30 08:56:41 2013
@@ -3584,8 +3584,12 @@ namespace {
         NewTL.setNameLoc(TL.getNameLoc());
         return Result;
       } else {
-        QualType Result = RebuildAutoType(Replacement,
-                                          TL.getTypePtr()->isDecltypeAuto());
+        bool Dependent =
+          !Replacement.isNull() && Replacement->isDependentType();
+        QualType Result =
+          SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,
+                                      TL.getTypePtr()->isDecltypeAuto(),
+                                      Dependent);
         AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
         NewTL.setNameLoc(TL.getNameLoc());
         return Result;
@@ -3597,41 +3601,6 @@ namespace {
       return E;
     }
   };
-
-  /// Determine whether the specified type (which contains an 'auto' type
-  /// specifier) is dependent. This is not trivial, because the 'auto' specifier
-  /// itself claims to be type-dependent.
-  bool isDependentAutoType(QualType Ty) {
-    while (1) {
-      QualType Pointee = Ty->getPointeeType();
-      if (!Pointee.isNull()) {
-        Ty = Pointee;
-      } else if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()){
-        if (MPT->getClass()->isDependentType())
-          return true;
-        Ty = MPT->getPointeeType();
-      } else if (const FunctionProtoType *FPT = Ty->getAs<FunctionProtoType>()){
-        for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(),
-                                                  E = FPT->arg_type_end();
-             I != E; ++I)
-          if ((*I)->isDependentType())
-            return true;
-        Ty = FPT->getResultType();
-      } else if (Ty->isDependentSizedArrayType()) {
-        return true;
-      } else if (const ArrayType *AT = Ty->getAsArrayTypeUnsafe()) {
-        Ty = AT->getElementType();
-      } else if (Ty->getAs<DependentSizedExtVectorType>()) {
-        return true;
-      } else if (const VectorType *VT = Ty->getAs<VectorType>()) {
-        Ty = VT->getElementType();
-      } else {
-        break;
-      }
-    }
-    assert(Ty->getAs<AutoType>() && "didn't find 'auto' in auto type");
-    return false;
-  }
 }
 
 /// \brief Deduce the type for an auto type-specifier (C++0x [dcl.spec.auto]p6)
@@ -3654,8 +3623,9 @@ Sema::DeduceAutoType(TypeSourceInfo *Typ
     Init = result.take();
   }
 
-  if (Init->isTypeDependent() || isDependentAutoType(Type->getType())) {
-    Result = Type;
+  if (Init->isTypeDependent() || Type->getType()->isDependentType()) {
+    Result =
+        SubstituteAutoTransform(*this, Context.DependentTy).TransformType(Type);
     return DAR_Succeeded;
   }
 
@@ -3749,6 +3719,10 @@ Sema::DeduceAutoType(TypeSourceInfo *Typ
   return DAR_Succeeded;
 }
 
+QualType Sema::SubstAutoType(QualType Type, QualType Deduced) {
+  return SubstituteAutoTransform(*this, Deduced).TransformType(Type);
+}
+
 void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
   if (isa<InitListExpr>(Init))
     Diag(VDecl->getLocation(),

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Apr 30 08:56:41 2013
@@ -2569,11 +2569,11 @@ static TypeSourceInfo *GetFullTypeForDec
 
       if (const AutoType *AT = T->getContainedAutoType()) {
         // We've already diagnosed this for decltype(auto).
-        if (!AT->isDecltypeAuto()) {
+        if (!AT->isDecltypeAuto())
           S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
             << getPrintableNameForEntity(Name) << T;
-          D.setInvalidType(true);
-        }
+        T = QualType();
+        break;
       }
 
       T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
@@ -3831,7 +3831,7 @@ static bool handleObjCOwnershipTypeAttr(
                                        QualType &type) {
   bool NonObjCPointer = false;
 
-  if (!type->isDependentType()) {
+  if (!type->isDependentType() && !type->isUndeducedType()) {
     if (const PointerType *ptr = type->getAs<PointerType>()) {
       QualType pointee = ptr->getPointeeType();
       if (pointee->isObjCRetainableType() || pointee->isPointerType())

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Apr 30 08:56:41 2013
@@ -764,6 +764,9 @@ public:
   ///
   /// By default, builds a new AutoType with the given deduced type.
   QualType RebuildAutoType(QualType Deduced, bool IsDecltypeAuto) {
+    // Note, IsDependent is always false here: we implicitly convert an 'auto'
+    // which has been deduced to a dependent type into an undeduced 'auto', so
+    // that we'll retry deduction after the transformation.
     return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto);
   }
 
@@ -4500,7 +4503,8 @@ QualType TreeTransform<Derived>::Transfo
   }
 
   QualType Result = TL.getType();
-  if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced) {
+  if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced ||
+      T->isDependentType()) {
     Result = getDerived().RebuildAutoType(NewDeduced, T->isDecltypeAuto());
     if (Result.isNull())
       return QualType();

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Apr 30 08:56:41 2013
@@ -4641,7 +4641,8 @@ QualType ASTReader::readTypeRecord(unsig
   case TYPE_AUTO: {
     QualType Deduced = readType(*Loc.F, Record, Idx);
     bool IsDecltypeAuto = Record[Idx++];
-    return Context.getAutoType(Deduced, IsDecltypeAuto);
+    bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;
+    return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent);
   }
 
   case TYPE_RECORD: {

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Apr 30 08:56:41 2013
@@ -246,6 +246,8 @@ void ASTTypeWriter::VisitUnaryTransformT
 void ASTTypeWriter::VisitAutoType(const AutoType *T) {
   Writer.AddTypeRef(T->getDeducedType(), Record);
   Record.push_back(T->isDecltypeAuto());
+  if (T->getDeducedType().isNull())
+    Record.push_back(T->isDependentType());
   Code = TYPE_AUTO;
 }
 

Modified: cfe/trunk/test/SemaCXX/condition.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/condition.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/condition.cpp (original)
+++ cfe/trunk/test/SemaCXX/condition.cpp Tue Apr 30 08:56:41 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s 
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s 
 
 void test() {
   int x;
@@ -6,7 +6,7 @@ void test() {
   if (int x=0) ++x;
 
   typedef int arr[10];
-  while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{array initializer must be an initializer list}}
+  while (arr x={0}) ; // expected-error {{an array type is not allowed here}}
   while (int f()=0) ; // expected-error {{a function type is not allowed here}}
 
   struct S {} s;
@@ -19,9 +19,7 @@ void test() {
   while (struct NewS *x=0) ;
   while (struct S {} *x=0) ; // expected-error {{types may not be defined in conditions}}
   while (struct {} *x=0) ; // expected-error {{types may not be defined in conditions}}
-  switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} \
-  // expected-warning{{enumeration value 'E' not handled in switch}} expected-warning {{switch statement has empty body}} \
-  // expected-note{{put the semicolon on a separate line}}
+  switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}}
 
   if (int x=0) { // expected-note 2 {{previous definition is here}}
     int x;  // expected-error {{redefinition of 'x'}}

Modified: cfe/trunk/test/SemaCXX/cxx11-crashes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-crashes.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx11-crashes.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx11-crashes.cpp Tue Apr 30 08:56:41 2013
@@ -70,7 +70,9 @@ namespace b6981007 {
     for (auto x : s) {
       // We used to attempt to evaluate the initializer of this variable,
       // and crash because it has an undeduced type.
-      const int &n(x);
+      // FIXME: We should set the loop variable to be invalid if we can't build
+      // the loop, to suppress this follow-on error.
+      const int &n(x); // expected-error {{could not bind to an lvalue of type 'auto'}}
     }
   }
 }

Modified: cfe/trunk/test/SemaCXX/for-range-unused.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-unused.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/for-range-unused.cpp (original)
+++ cfe/trunk/test/SemaCXX/for-range-unused.cpp Tue Apr 30 08:56:41 2013
@@ -7,7 +7,7 @@ template <typename T>
     void doIt() {
       int a; // expected-warning {{unused variable 'a'}}
 
-      for (auto& e : elements)
+      for (auto& e : elements) // expected-warning {{unused variable 'e'}}
         ;
     }
 
@@ -17,5 +17,5 @@ template <typename T>
 
 int main(int, char**) {
   Vector<int>    vector;
-  vector.doIt();
+  vector.doIt(); // expected-note {{here}}
 }

Modified: cfe/trunk/test/SemaTemplate/dependent-names.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-names.cpp?rev=180789&r1=180788&r2=180789&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/dependent-names.cpp (original)
+++ cfe/trunk/test/SemaTemplate/dependent-names.cpp Tue Apr 30 08:56:41 2013
@@ -264,7 +264,7 @@ namespace PR10053 {
 }
 
 namespace PR10187 {
-  namespace A {
+  namespace A1 {
     template<typename T>
     struct S {
       void f() {
@@ -278,6 +278,25 @@ namespace PR10187 {
     }
   }
 
+  namespace A2 {
+    template<typename T>
+    struct S {
+      void f() {
+        for (auto &a : e)
+          __range(a); // expected-error {{undeclared identifier '__range'}}
+      }
+      T e[10];
+    };
+    void g() {
+      S<int>().f(); // expected-note {{here}}
+    }
+    struct X {};
+    void __range(X);
+    void h() {
+      S<X>().f();
+    }
+  }
+
   namespace B {
     template<typename T> void g(); // expected-note {{not viable}}
     template<typename T> void f() {





More information about the cfe-commits mailing list