[cfe-commits] r126069 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Sema/ lib/Serialization/ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/ test/CXX/dcl.decl/dcl.meaning/dcl.array/ test/CXX/dcl.decl/dcl.meaning/dcl.fct/ test/CXX/expr/expr.unary/expr.new/ test/Misc/ test/SemaCXX/ tools/libclang/

Richard Smith richard-llvm at metafoo.co.uk
Sat Feb 19 19:19:35 PST 2011


Author: rsmith
Date: Sat Feb 19 21:19:35 2011
New Revision: 126069

URL: http://llvm.org/viewvc/llvm-project?rev=126069&view=rev
Log:
Implement the C++0x deduced 'auto' feature.

This fixes PR 8738, 9060 and 9132.


Added:
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp
    cfe/trunk/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp
    cfe/trunk/test/SemaCXX/dependent-auto.cpp
    cfe/trunk/test/SemaCXX/redeclared-auto.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/AST/TypeLoc.h
    cfe/trunk/include/clang/AST/TypeNodes.def
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTDiagnostic.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/MicrosoftMangle.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/AST/TypeLoc.cpp
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/CodeGen/CGRTTI.cpp
    cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTCommon.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp
    cfe/trunk/test/Misc/diag-aka-types.cpp
    cfe/trunk/test/SemaCXX/trailing-return-0x.cpp
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CIndexUSRs.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Sat Feb 19 21:19:35 2011
@@ -412,7 +412,7 @@
   CanQualType FloatTy, DoubleTy, LongDoubleTy;
   CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
   CanQualType VoidPtrTy, NullPtrTy;
-  CanQualType OverloadTy, UndeducedAutoTy;
+  CanQualType OverloadTy;
   CanQualType DependentTy;
   CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
 
@@ -740,6 +740,9 @@
   /// getDecltypeType - C++0x decltype.
   QualType getDecltypeType(Expr *e) const;
 
+  /// getAutoType - C++0x deduced auto type.
+  QualType getAutoType(QualType DeducedType) const;
+
   /// getTagDeclType - Return the unique reference to the type for the
   /// specified TagDecl (struct/union/class/enum) decl.
   QualType getTagDeclType(const TagDecl *Decl) const;

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sat Feb 19 21:19:35 2011
@@ -651,6 +651,10 @@
   /// \brief Whether this local variable could be allocated in the return
   /// slot of its function, enabling the named return value optimization (NRVO).
   bool NRVOVariable : 1;
+
+  /// \brief Whether this variable has a deduced C++0x auto type for which we're
+  /// currently parsing the initializer.
+  bool ParsingAutoInit : 1;
   
   friend class StmtIteratorBase;
   friend class ASTDeclReader;
@@ -661,7 +665,7 @@
           StorageClass SCAsWritten)
     : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
       ThreadSpecified(false), HasCXXDirectInit(false),
-      ExceptionVar(false), NRVOVariable(false) {
+      ExceptionVar(false), NRVOVariable(false), ParsingAutoInit(false) {
     SClass = SC;
     SClassAsWritten = SCAsWritten;
   }
@@ -885,6 +889,18 @@
 
   void setInit(Expr *I);
 
+  /// \brief Check whether we are in the process of parsing an initializer
+  /// needed to deduce the type of this variable.
+  bool isParsingAutoInit() const {
+    return ParsingAutoInit;
+  }
+
+  /// \brief Note whether we are currently parsing an initializer needed to
+  /// deduce the type of this variable.
+  void setParsingAutoInit(bool P) {
+    ParsingAutoInit = P;
+  }
+
   EvaluatedStmt *EnsureEvaluatedStmt() const {
     EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
     if (!Eval) {

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Sat Feb 19 21:19:35 2011
@@ -715,6 +715,10 @@
     TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
   })
 
+DEF_TRAVERSE_TYPE(AutoType, {
+    TRY_TO(TraverseType(T->getDeducedType()));
+  })
+
 DEF_TRAVERSE_TYPE(RecordType, { })
 DEF_TRAVERSE_TYPE(EnumType, { })
 DEF_TRAVERSE_TYPE(TemplateTypeParmType, { })
@@ -923,6 +927,10 @@
     TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
   })
 
+DEF_TRAVERSE_TYPELOC(AutoType, {
+    TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
+  })
+
 DEF_TRAVERSE_TYPELOC(RecordType, { })
 DEF_TRAVERSE_TYPELOC(EnumType, { })
 DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { })

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Sat Feb 19 21:19:35 2011
@@ -1328,6 +1328,11 @@
   /// because the type is a RecordType or because it is the injected-class-name 
   /// type of a class template or class template partial specialization.
   CXXRecordDecl *getAsCXXRecordDecl() const;
+
+  /// \brief Get the AutoType whose type will be deduced for a variable with
+  /// an initializer of this type. This looks through declarators like pointer
+  /// types, but not through decltype or typedefs.
+  AutoType *getContainedAutoType() const;
   
   /// Member-template getAs<specific type>'.  Look through sugar for
   /// an instance of <specific type>.   This scheme will eventually
@@ -1478,9 +1483,6 @@
 
     Overload,  // This represents the type of an overloaded function declaration.
 
-    UndeducedAuto, // In C++0x, this represents the type of an auto variable
-                   // that has not been deduced yet.
-
     /// The primitive Objective C 'id' type.  The type pointed to by the
     /// user-visible 'id' type.  Only ever shows up in an AST as the base
     /// type of an ObjCObjectType.
@@ -1528,8 +1530,7 @@
   /// i.e. a type which cannot appear in arbitrary positions in a
   /// fully-formed expression.
   bool isPlaceholderType() const {
-    return getKind() == Overload ||
-           getKind() == UndeducedAuto;
+    return getKind() == Overload;
   }
 
   static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
@@ -3014,6 +3015,48 @@
   static bool classof(const SubstTemplateTypeParmPackType *T) { return true; }
 };
 
+/// \brief Represents a C++0x 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.
+class AutoType : public Type, public llvm::FoldingSetNode {
+  AutoType(QualType DeducedType)
+    : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
+           /*Dependent=*/DeducedType.isNull(),
+           /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
+    assert((DeducedType.isNull() || !DeducedType->isDependentType()) &&
+           "deduced a dependent type for auto");
+  }
+
+  friend class ASTContext;  // ASTContext creates these
+
+public:
+  bool isSugared() const { return isDeduced(); }
+  QualType desugar() const { return getCanonicalTypeInternal(); }
+
+  QualType getDeducedType() const {
+    return isDeduced() ? getCanonicalTypeInternal() : QualType();
+  }
+  bool isDeduced() const {
+    return !isDependentType();
+  }
+
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, getDeducedType());
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &ID,
+                      QualType Deduced) {
+    ID.AddPointer(Deduced.getAsOpaquePtr());
+  }
+
+  static bool classof(const Type *T) {
+    return T->getTypeClass() == Auto;
+  }
+  static bool classof(const AutoType *T) { return true; }
+};
+
 /// \brief Represents the type of a template specialization as written
 /// in the source code.
 ///

Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Sat Feb 19 21:19:35 2011
@@ -1381,6 +1381,11 @@
                                                          DecltypeType> {
 };
 
+class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+                                                        AutoTypeLoc,
+                                                        AutoType> {
+};
+
 struct ElaboratedLocInfo {
   SourceLocation KeywordLoc;
   SourceRange QualifierRange;

Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Sat Feb 19 21:19:35 2011
@@ -93,6 +93,7 @@
 NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
 DEPENDENT_TYPE(SubstTemplateTypeParmPack, Type)
 NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Auto, Type)
 DEPENDENT_TYPE(InjectedClassName, Type)
 DEPENDENT_TYPE(DependentName, Type)
 DEPENDENT_TYPE(DependentTemplateSpecialization, Type)

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Feb 19 21:19:35 2011
@@ -892,16 +892,31 @@
 def err_auto_variable_cannot_appear_in_own_initializer : Error<
   "variable %0 declared with 'auto' type cannot appear in its own initializer">;
 def err_illegal_decl_array_of_auto : Error<
-  "'%0' declared as array of 'auto'">;
+  "'%0' declared as array of %1">;
+def err_new_array_of_auto : Error<
+  "cannot allocate array of 'auto'">;
 def err_auto_not_allowed : Error<
-  "'auto' not allowed in %select{function prototype|struct member|union member"
-  "|class member|exception declaration|template parameter|block literal}0">;
+  "'auto' not allowed %select{in function prototype|in struct member"
+  "|in union member|in class member|in exception declaration"
+  "|in template parameter|in block literal|in template argument|here}0">;
 def err_auto_var_requires_init : Error<
   "declaration of variable %0 with type %1 requires an initializer">;
+def err_auto_new_requires_ctor_arg : Error<
+  "new expression for type %0 requires a constructor argument">;
+def err_auto_var_init_multiple_expressions : Error<
+  "initializer for variable %0 with type %1 contains multiple expressions">;
+def err_auto_new_ctor_multiple_expressions : Error<
+  "new expression for type %0 contains multiple constructor arguments">;
 def err_auto_missing_trailing_return : Error<
   "'auto' return without trailing return type">;
 def err_trailing_return_without_auto : Error<
-  "trailing return type without 'auto' return">;
+  "function with trailing return type must specify return type 'auto', not %0">;
+def err_auto_var_deduction_failure : Error<
+  "variable %0 with type %1 has incompatible initializer of type %2">;
+def err_auto_new_deduction_failure : Error<
+  "new expression for type %0 has incompatible constructor argument of type %1">;
+def err_auto_different_deductions : Error<
+  "'auto' deduced as %0 in declaration of %1 and deduced as %2 in declaration of %3">;
 
 // C++0x override control
 def override_keyword_only_allowed_on_virtual_member_functions : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Feb 19 21:19:35 2011
@@ -730,7 +730,8 @@
   QualType BuildParenType(QualType T);
 
   TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S,
-                                       TagDecl **OwnedDecl = 0);
+                                       TagDecl **OwnedDecl = 0,
+                                       bool AllowAutoInTypeName = false);
   TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
                                                TypeSourceInfo *ReturnTypeInfo);
   /// \brief Package the given type and TSI into a ParsedType.
@@ -850,9 +851,9 @@
   bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
                                SourceLocation EqualLoc);
 
-  void AddInitializerToDecl(Decl *dcl, Expr *init);
-  void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
-  void ActOnUninitializedDecl(Decl *dcl, bool TypeContainsUndeducedAuto);
+  void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit,
+                            bool TypeMayContainAuto);
+  void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto);
   void ActOnInitializerError(Decl *Dcl);
   void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
   DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
@@ -1058,6 +1059,7 @@
   void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
   bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
   bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
+  void MergeVarDeclTypes(VarDecl *New, VarDecl *Old);
   void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
   bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
 
@@ -2237,7 +2239,8 @@
   void AddCXXDirectInitializerToDecl(Decl *Dcl,
                                      SourceLocation LParenLoc,
                                      MultiExprArg Exprs,
-                                     SourceLocation RParenLoc);
+                                     SourceLocation RParenLoc,
+                                     bool TypeMayContainAuto);
 
   /// InitializeVarWithConstructor - Creates an CXXConstructExpr
   /// and sets it as the initializer for the the passed in VarDecl.
@@ -2458,7 +2461,8 @@
                          Expr *ArraySize,
                          SourceLocation ConstructorLParen,
                          MultiExprArg ConstructorArgs,
-                         SourceLocation ConstructorRParen);
+                         SourceLocation ConstructorRParen,
+                         bool TypeMayContainAuto = true);
 
   bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
                           SourceRange R);
@@ -3706,6 +3710,8 @@
                           FunctionDecl *&Specialization,
                           sema::TemplateDeductionInfo &Info);
 
+  bool DeduceAutoType(QualType AutoType, Expr *Initializer, QualType &Result);
+
   FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
                                                    FunctionTemplateDecl *FT2,
                                                    SourceLocation Loc,

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Sat Feb 19 21:19:35 2011
@@ -578,7 +578,9 @@
       /// \brief An AttributedType record.
       TYPE_ATTRIBUTED               = 36,
       /// \brief A SubstTemplateTypeParmPackType record.
-      TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37
+      TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
+      /// \brief A AutoType record.
+      TYPE_AUTO                  = 38
     };
 
     /// \brief The type IDs for special types constructed by semantic

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Feb 19 21:19:35 2011
@@ -380,10 +380,6 @@
   // Placeholder type for functions.
   InitBuiltinType(OverloadTy,          BuiltinType::Overload);
 
-  // Placeholder type for C++0x auto declarations whose real type has
-  // not yet been deduced.
-  InitBuiltinType(UndeducedAutoTy,     BuiltinType::UndeducedAuto);
-
   // C99 6.2.5p11.
   FloatComplexTy      = getComplexType(FloatTy);
   DoubleComplexTy     = getComplexType(DoubleTy);
@@ -875,6 +871,12 @@
     return getTypeInfo(cast<SubstTemplateTypeParmType>(T)->
                        getReplacementType().getTypePtr());
 
+  case Type::Auto: {
+    const AutoType *A = cast<AutoType>(T);
+    assert(A->isDeduced() && "Cannot request the size of a dependent type");
+    return getTypeInfo(cast<AutoType>(T)->getDeducedType().getTypePtr());
+  }
+
   case Type::Paren:
     return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
 
@@ -1532,6 +1534,7 @@
   case Type::DependentTemplateSpecialization:
   case Type::TemplateTypeParm:
   case Type::SubstTemplateTypeParmPack:
+  case Type::Auto:
   case Type::PackExpansion:
     llvm_unreachable("type should never be variably-modified");
 
@@ -2680,6 +2683,14 @@
   return QualType(dt, 0);
 }
 
+/// getAutoType - Unlike many "get<Type>" functions, we don't unique
+/// AutoType AST's.
+QualType ASTContext::getAutoType(QualType DeducedType) const {
+  AutoType *at = new (*this, TypeAlignment) AutoType(DeducedType);
+  Types.push_back(at);
+  return QualType(at, 0);
+}
+
 /// getTagDeclType - Return the unique reference to the type for the
 /// specified TagDecl (struct/union/class/enum) decl.
 QualType ASTContext::getTagDeclType(const TagDecl *Decl) const {

Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Sat Feb 19 21:19:35 2011
@@ -28,18 +28,26 @@
     const Type *Ty = QC.strip(QT);
 
     // Don't aka just because we saw an elaborated type...
-    if (isa<ElaboratedType>(Ty)) {
-      QT = cast<ElaboratedType>(Ty)->desugar();
+    if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) {
+      QT = ET->desugar();
       continue;
     }
     // ... or a paren type ...
-    if (isa<ParenType>(Ty)) {
-      QT = cast<ParenType>(Ty)->desugar();
+    if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
+      QT = PT->desugar();
       continue;
     }
-    // ...or a substituted template type parameter.
-    if (isa<SubstTemplateTypeParmType>(Ty)) {
-      QT = cast<SubstTemplateTypeParmType>(Ty)->desugar();
+    // ...or a substituted template type parameter ...
+    if (const SubstTemplateTypeParmType *ST =
+          dyn_cast<SubstTemplateTypeParmType>(Ty)) {
+      QT = ST->desugar();
+      continue;
+    }
+    // ... or an auto type.
+    if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
+      if (!AT->isSugared())
+        break;
+      QT = AT->desugar();
       continue;
     }
 

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Sat Feb 19 21:19:35 2011
@@ -64,6 +64,7 @@
     // FIXME: DependentTypeOfExprType
     QualType VisitTypeOfType(const TypeOfType *T);
     QualType VisitDecltypeType(const DecltypeType *T);
+    QualType VisitAutoType(const AutoType *T);
     // FIXME: DependentDecltypeType
     QualType VisitRecordType(const RecordType *T);
     QualType VisitEnumType(const EnumType *T);
@@ -604,6 +605,13 @@
       return false;
     break;
 
+  case Type::Auto:
+    if (!IsStructurallyEquivalent(Context,
+                                  cast<AutoType>(T1)->getDeducedType(),
+                                  cast<AutoType>(T2)->getDeducedType()))
+      return false;
+    break;
+
   case Type::Record:
   case Type::Enum:
     if (!IsStructurallyEquivalent(Context,
@@ -1347,9 +1355,6 @@
     
   case BuiltinType::Overload: return Importer.getToContext().OverloadTy;
   case BuiltinType::Dependent: return Importer.getToContext().DependentTy;
-  case BuiltinType::UndeducedAuto: 
-    // FIXME: Make sure that the "to" context supports C++0x!
-    return Importer.getToContext().UndeducedAutoTy;
 
   case BuiltinType::ObjCId:
     // FIXME: Make sure that the "to" context supports Objective-C!
@@ -1550,6 +1555,7 @@
 }
 
 QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
+  // FIXME: Make sure that the "to" context supports C++0x!
   Expr *ToExpr = Importer.Import(T->getUnderlyingExpr());
   if (!ToExpr)
     return QualType();
@@ -1557,6 +1563,19 @@
   return Importer.getToContext().getDecltypeType(ToExpr);
 }
 
+QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
+  // FIXME: Make sure that the "to" context supports C++0x!
+  QualType FromDeduced = T->getDeducedType();
+  QualType ToDeduced;
+  if (!FromDeduced.isNull()) {
+    ToDeduced = Importer.Import(FromDeduced);
+    if (ToDeduced.isNull())
+      return QualType();
+  }
+  
+  return Importer.getToContext().getAutoType(ToDeduced);
+}
+
 QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
   RecordDecl *ToDecl
     = dyn_cast_or_null<RecordDecl>(Importer.Import(T->getDecl()));

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Sat Feb 19 21:19:35 2011
@@ -1313,9 +1313,6 @@
     assert(false &&
            "Overloaded and dependent types shouldn't get to name mangling");
     break;
-  case BuiltinType::UndeducedAuto:
-    assert(0 && "Should not see undeduced auto here");
-    break;
   case BuiltinType::ObjCId: Out << "11objc_object"; break;
   case BuiltinType::ObjCClass: Out << "10objc_class"; break;
   case BuiltinType::ObjCSel: Out << "13objc_selector"; break;
@@ -1648,6 +1645,12 @@
   Out << 'E';
 }
 
+void CXXNameMangler::mangleType(const AutoType *T) {
+  QualType D = T->getDeducedType();
+  assert(!D.isNull() && "can't mangle undeduced auto type");
+  mangleType(D);
+}
+
 void CXXNameMangler::mangleIntegerLiteral(QualType T,
                                           const llvm::APSInt &Value) {
   //  <expr-primary> ::= L <type> <value number> E # integer literal

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Sat Feb 19 21:19:35 2011
@@ -720,9 +720,6 @@
     assert(false &&
            "Overloaded and dependent types shouldn't get to name mangling");
     break;
-  case BuiltinType::UndeducedAuto:
-    assert(0 && "Should not see undeduced auto here");
-    break;
   case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break;
   case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break;
   case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break;
@@ -1119,6 +1116,10 @@
   assert(false && "Don't know how to mangle DecltypeTypes yet!");
 }
 
+void MicrosoftCXXNameMangler::mangleType(const AutoType *T) {
+  assert(false && "Don't know how to mangle AutoTypes yet!");
+}
+
 void MicrosoftMangleContext::mangleName(const NamedDecl *D,
                                         llvm::raw_ostream &Out) {
   assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Sat Feb 19 21:19:35 2011
@@ -432,6 +432,61 @@
   return 0;
 }
 
+namespace {
+  class GetContainedAutoVisitor :
+    public TypeVisitor<GetContainedAutoVisitor, AutoType*> {
+  public:
+    using TypeVisitor<GetContainedAutoVisitor, AutoType*>::Visit;
+    AutoType *Visit(QualType T) {
+      if (T.isNull())
+        return 0;
+      return Visit(T.getTypePtr());
+    }
+
+    // The 'auto' type itself.
+    AutoType *VisitAutoType(const AutoType *AT) {
+      return const_cast<AutoType*>(AT);
+    }
+
+    // Only these types can contain the desired 'auto' type.
+    AutoType *VisitPointerType(const PointerType *T) {
+      return Visit(T->getPointeeType());
+    }
+    AutoType *VisitBlockPointerType(const BlockPointerType *T) {
+      return Visit(T->getPointeeType());
+    }
+    AutoType *VisitReferenceType(const ReferenceType *T) {
+      return Visit(T->getPointeeTypeAsWritten());
+    }
+    AutoType *VisitMemberPointerType(const MemberPointerType *T) {
+      return Visit(T->getPointeeType());
+    }
+    AutoType *VisitArrayType(const ArrayType *T) {
+      return Visit(T->getElementType());
+    }
+    AutoType *VisitDependentSizedExtVectorType(
+      const DependentSizedExtVectorType *T) {
+      return Visit(T->getElementType());
+    }
+    AutoType *VisitVectorType(const VectorType *T) {
+      return Visit(T->getElementType());
+    }
+    AutoType *VisitFunctionType(const FunctionType *T) {
+      return Visit(T->getResultType());
+    }
+    AutoType *VisitParenType(const ParenType *T) {
+      return Visit(T->getInnerType());
+    }
+    AutoType *VisitAttributedType(const AttributedType *T) {
+      return Visit(T->getModifiedType());
+    }
+  };
+}
+
+AutoType *Type::getContainedAutoType() const {
+  return GetContainedAutoVisitor().Visit(this);
+}
+
 bool Type::isIntegerType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
     return BT->getKind() >= BuiltinType::Bool &&
@@ -1066,7 +1121,6 @@
   case NullPtr:           return "nullptr_t";
   case Overload:          return "<overloaded function type>";
   case Dependent:         return "<dependent type>";
-  case UndeducedAuto:     return "auto";
   case ObjCId:            return "id";
   case ObjCClass:         return "Class";
   case ObjCSel:           return "SEL";

Modified: cfe/trunk/lib/AST/TypeLoc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypeLoc.cpp (original)
+++ cfe/trunk/lib/AST/TypeLoc.cpp Sat Feb 19 21:19:35 2011
@@ -191,9 +191,7 @@
     case BuiltinType::WChar_S:
     case BuiltinType::WChar_U:
       return TST_wchar;
-    case BuiltinType::UndeducedAuto:
-      return TST_auto;
-        
+
     case BuiltinType::UChar:
     case BuiltinType::UShort:
     case BuiltinType::UInt:

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Sat Feb 19 21:19:35 2011
@@ -80,6 +80,8 @@
   bool CanPrefixQualifiers = false;
   
   Type::TypeClass TC = T->getTypeClass();
+  if (const AutoType *AT = dyn_cast<AutoType>(T))
+    TC = AT->desugar()->getTypeClass();
   if (const SubstTemplateTypeParmType *Subst
                                       = dyn_cast<SubstTemplateTypeParmType>(T))
     TC = Subst->getReplacementType()->getTypeClass();
@@ -129,6 +131,7 @@
     case Type::Attributed:
     case Type::PackExpansion:
     case Type::SubstTemplateTypeParm:
+    case Type::Auto:
       CanPrefixQualifiers = false;
       break;
   }
@@ -493,6 +496,17 @@
   S = "decltype(" + s.str() + ")" + S;
 }
 
+void TypePrinter::printAuto(const AutoType *T, std::string &S) { 
+  // If the type has been deduced, do not print 'auto'.
+  if (T->isDeduced()) {
+    print(T->getDeducedType(), S);
+  } else {
+    if (!S.empty())    // Prefix the basic type, e.g. 'auto X'.
+      S = ' ' + S;
+    S = "auto" + S;
+  }
+}
+
 /// Appends the given scope to the end of a string.
 void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
   if (DC->isTranslationUnit()) return;

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Sat Feb 19 21:19:35 2011
@@ -1465,6 +1465,7 @@
   case Type::TypeOfExpr:
   case Type::TypeOf:
   case Type::Decltype:
+  case Type::Auto:
     llvm_unreachable("type should have been unwrapped!");
     return llvm::DIType();      
   }

Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Sat Feb 19 21:19:35 2011
@@ -195,7 +195,6 @@
       
     case BuiltinType::Overload:
     case BuiltinType::Dependent:
-    case BuiltinType::UndeducedAuto:
       assert(false && "Should not see this type here!");
       
     case BuiltinType::ObjCId:

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Sat Feb 19 21:19:35 2011
@@ -253,7 +253,6 @@
     
     case BuiltinType::Overload:
     case BuiltinType::Dependent:
-    case BuiltinType::UndeducedAuto:
       assert(0 && "Unexpected builtin type!");
       break;
     }

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Feb 19 21:19:35 2011
@@ -392,7 +392,7 @@
   ParsingDeclSpec DS(*this);
   DS.takeAttributesFrom(attrs);
   ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
-                            getDeclSpecContextFromDeclaratorContext(Context));
+                             getDeclSpecContextFromDeclaratorContext(Context));
   StmtResult R = Actions.ActOnVlaStmt(DS);
   if (R.isUsable())
     Stmts.push_back(R.release());
@@ -587,6 +587,9 @@
     }
   }
 
+  bool TypeContainsAuto =
+    D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+
   // Parse declarator '=' initializer.
   if (isTokenEqualOrMistypedEqualEqual(
                                diag::err_invalid_equalequal_after_declarator)) {
@@ -622,7 +625,8 @@
         SkipUntil(tok::comma, true, true);
         Actions.ActOnInitializerError(ThisDecl);
       } else
-        Actions.AddInitializerToDecl(ThisDecl, Init.take());
+        Actions.AddInitializerToDecl(ThisDecl, Init.take(),
+                                     /*DirectInit=*/false, TypeContainsAuto);
     }
   } else if (Tok.is(tok::l_paren)) {
     // Parse C++ direct initializer: '(' expression-list ')'
@@ -656,12 +660,11 @@
 
       Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
                                             move_arg(Exprs),
-                                            RParenLoc);
+                                            RParenLoc,
+                                            TypeContainsAuto);
     }
   } else {
-    bool TypeContainsUndeducedAuto =
-      D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
-    Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsUndeducedAuto);
+    Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto);
   }
 
   return ThisDecl;

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sat Feb 19 21:19:35 2011
@@ -827,7 +827,8 @@
     ConsumeToken();
     ExprResult AssignExpr(ParseAssignmentExpression());
     if (!AssignExpr.isInvalid()) 
-      Actions.AddInitializerToDecl(DeclOut, AssignExpr.take());
+      Actions.AddInitializerToDecl(DeclOut, AssignExpr.take(), false,
+                                   DS.getTypeSpecType() == DeclSpec::TST_auto);
   } else {
     // FIXME: C++0x allows a braced-init-list
     Diag(Tok, diag::err_expected_equal_after_declarator);

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Sat Feb 19 21:19:35 2011
@@ -586,7 +586,6 @@
         
       case BuiltinType::Overload:
       case BuiltinType::Dependent:
-      case BuiltinType::UndeducedAuto:
         return STC_Other;
         
       case BuiltinType::ObjCId:

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Feb 19 21:19:35 2011
@@ -1471,48 +1471,26 @@
   return false;
 }
 
-/// MergeVarDecl - We just parsed a variable 'New' which has the same name
-/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
-/// situation, merging decls or emitting diagnostics as appropriate.
+/// MergeVarDecl - We parsed a variable 'New' which has the same name and scope
+/// as a previous declaration 'Old'.  Figure out how to merge their types,
+/// emitting diagnostics as appropriate.
 ///
-/// Tentative definition rules (C99 6.9.2p2) are checked by
-/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
-/// definitions here, since the initializer hasn't been attached.
+/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back
+/// to here in AddInitializerToDecl and AddCXXDirectInitializerToDecl. We can't
+/// check them before the initializer is attached.
 ///
-void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
-  // If the new decl is already invalid, don't do any other checking.
-  if (New->isInvalidDecl())
+void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) {
+  if (New->isInvalidDecl() || Old->isInvalidDecl())
     return;
 
-  // Verify the old decl was also a variable.
-  VarDecl *Old = 0;
-  if (!Previous.isSingleResult() ||
-      !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
-    Diag(New->getLocation(), diag::err_redefinition_different_kind)
-      << New->getDeclName();
-    Diag(Previous.getRepresentativeDecl()->getLocation(),
-         diag::note_previous_definition);
-    return New->setInvalidDecl();
-  }
-
-  // C++ [class.mem]p1:
-  //   A member shall not be declared twice in the member-specification [...]
-  // 
-  // Here, we need only consider static data members.
-  if (Old->isStaticDataMember() && !New->isOutOfLine()) {
-    Diag(New->getLocation(), diag::err_duplicate_member) 
-      << New->getIdentifier();
-    Diag(Old->getLocation(), diag::note_previous_declaration);
-    New->setInvalidDecl();
-  }
-  
-  MergeDeclAttributes(New, Old, Context);
-
-  // Merge the types
   QualType MergedT;
   if (getLangOptions().CPlusPlus) {
-    if (Context.hasSameType(New->getType(), Old->getType()))
-      MergedT = New->getType();
+    AutoType *AT = New->getType()->getContainedAutoType();
+    if (AT && !AT->isDeduced()) {
+      // We don't know what the new type is until the initializer is attached.
+      return;
+    } else if (Context.hasSameType(New->getType(), Old->getType()))
+      return;
     // C++ [basic.link]p10:
     //   [...] the types specified by all declarations referring to a given
     //   object or function shall be identical, except that declarations for an
@@ -1536,7 +1514,8 @@
         MergedT = Old->getType();
     } else if (New->getType()->isObjCObjectPointerType()
                && Old->getType()->isObjCObjectPointerType()) {
-        MergedT = Context.mergeObjCGCQualifiers(New->getType(), Old->getType());
+        MergedT = Context.mergeObjCGCQualifiers(New->getType(),
+                                                        Old->getType());
     }
   } else {
     MergedT = Context.mergeTypes(New->getType(), Old->getType());
@@ -1548,6 +1527,49 @@
     return New->setInvalidDecl();
   }
   New->setType(MergedT);
+}
+
+/// MergeVarDecl - We just parsed a variable 'New' which has the same name
+/// and scope as a previous declaration 'Old'.  Figure out how to resolve this
+/// situation, merging decls or emitting diagnostics as appropriate.
+///
+/// Tentative definition rules (C99 6.9.2p2) are checked by
+/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
+/// definitions here, since the initializer hasn't been attached.
+///
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
+  // If the new decl is already invalid, don't do any other checking.
+  if (New->isInvalidDecl())
+    return;
+
+  // Verify the old decl was also a variable.
+  VarDecl *Old = 0;
+  if (!Previous.isSingleResult() ||
+      !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
+    Diag(New->getLocation(), diag::err_redefinition_different_kind)
+      << New->getDeclName();
+    Diag(Previous.getRepresentativeDecl()->getLocation(),
+         diag::note_previous_definition);
+    return New->setInvalidDecl();
+  }
+
+  // C++ [class.mem]p1:
+  //   A member shall not be declared twice in the member-specification [...]
+  // 
+  // Here, we need only consider static data members.
+  if (Old->isStaticDataMember() && !New->isOutOfLine()) {
+    Diag(New->getLocation(), diag::err_duplicate_member) 
+      << New->getIdentifier();
+    Diag(Old->getLocation(), diag::note_previous_declaration);
+    New->setInvalidDecl();
+  }
+  
+  MergeDeclAttributes(New, Old, Context);
+
+  // Merge the types.
+  MergeVarDeclTypes(New, Old);
+  if (New->isInvalidDecl())
+    return;
 
   // C99 6.2.2p4: Check if we have a static decl followed by a non-static.
   if (New->getStorageClass() == SC_Static &&
@@ -3004,6 +3026,12 @@
     NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
                             II, R, TInfo, SC, SCAsWritten);
 
+    // If this decl has an auto type in need of deduction, mark the VarDecl so
+    // we can diagnose uses of it in its own initializer.
+    if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto) {
+      NewVD->setParsingAutoInit(R->getContainedAutoType());
+    }
+
     if (D.isInvalidType() || Invalid)
       NewVD->setInvalidDecl();
 
@@ -4466,17 +4494,14 @@
   return true;
 }
 
-void Sema::AddInitializerToDecl(Decl *dcl, Expr *init) {
-  AddInitializerToDecl(dcl, init, /*DirectInit=*/false);
-}
-
 /// AddInitializerToDecl - Adds the initializer Init to the
 /// declaration dcl. If DirectInit is true, this is C++ direct
 /// initialization rather than copy initialization.
-void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
+void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
+                                bool DirectInit, bool TypeMayContainAuto) {
   // If there is no declaration, there was an error parsing it.  Just ignore
   // the initializer.
-  if (RealDecl == 0)
+  if (RealDecl == 0 || RealDecl->isInvalidDecl())
     return;
 
   if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) {
@@ -4507,6 +4532,25 @@
     return;
   }
 
+  // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+  if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
+    VDecl->setParsingAutoInit(false);
+
+    QualType DeducedType;
+    if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
+      Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+        << VDecl->getDeclName() << VDecl->getType() << Init->getType()
+        << Init->getSourceRange();
+      RealDecl->setInvalidDecl();
+      return;
+    }
+    VDecl->setType(DeducedType);
+
+    // If this is a redeclaration, check that the type we just deduced matches
+    // the previously declared type.
+    if (VarDecl *Old = VDecl->getPreviousDeclaration())
+      MergeVarDeclTypes(VDecl, Old);
+  }
   
 
   // A definition must end up with a complete type, which means it must be
@@ -4755,6 +4799,13 @@
   VarDecl *VD = dyn_cast<VarDecl>(D);
   if (!VD) return;
 
+  // Auto types are meaningless if we can't make sense of the initializer.
+  if (VD->isParsingAutoInit()) {
+    VD->setParsingAutoInit(false);
+    VD->setInvalidDecl();
+    return;
+  }
+
   QualType Ty = VD->getType();
   if (Ty->isDependentType()) return;
 
@@ -4779,7 +4830,7 @@
 }
 
 void Sema::ActOnUninitializedDecl(Decl *RealDecl,
-                                  bool TypeContainsUndeducedAuto) {
+                                  bool TypeMayContainAuto) {
   // If there is no declaration, there was an error parsing it. Just ignore it.
   if (RealDecl == 0)
     return;
@@ -4788,7 +4839,9 @@
     QualType Type = Var->getType();
 
     // C++0x [dcl.spec.auto]p3
-    if (TypeContainsUndeducedAuto) {
+    if (TypeMayContainAuto && Type->getContainedAutoType()) {
+      Var->setParsingAutoInit(false);
+
       Diag(Var->getLocation(), diag::err_auto_var_requires_init)
         << Var->getDeclName() << Type;
       Var->setInvalidDecl();
@@ -4999,6 +5052,41 @@
   if (DS.isTypeSpecOwned())
     Decls.push_back(DS.getRepAsDecl());
 
+  // C++0x [dcl.spec.auto]p7:
+  //   If the type deduced for the template parameter U is not the same in each
+  //   deduction, the program is ill-formed.
+  // FIXME: When initializer-list support is added, a distinction is needed
+  // between the deduced type U and the deduced type which 'auto' stands for.
+  //   auto a = 0, b = { 1, 2, 3 };
+  // is legal because the deduced type U is 'int' in both cases.
+  bool TypeContainsAuto = DS.getTypeSpecType() == DeclSpec::TST_auto;
+  if (TypeContainsAuto && NumDecls > 1) {
+    QualType Deduced;
+    CanQualType DeducedCanon;
+    VarDecl *DeducedDecl = 0;
+    for (unsigned i = 0; i != NumDecls; ++i) {
+      if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) {
+        AutoType *AT = D->getType()->getContainedAutoType();
+        if (AT && AT->isDeduced()) {
+          QualType U = AT->getDeducedType();
+          CanQualType UCanon = Context.getCanonicalType(U);
+          if (Deduced.isNull()) {
+            Deduced = U;
+            DeducedCanon = UCanon;
+            DeducedDecl = D;
+          } else if (DeducedCanon != UCanon) {
+            Diag(DS.getTypeSpecTypeLoc(), diag::err_auto_different_deductions)
+              << Deduced << DeducedDecl->getDeclName()
+              << U << D->getDeclName()
+              << DeducedDecl->getInit()->getSourceRange()
+              << D->getInit()->getSourceRange();
+            break;
+          }
+        }
+      }
+    }
+  }
+
   for (unsigned i = 0; i != NumDecls; ++i)
     if (Decl *D = Group[i])
       Decls.push_back(D);

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Feb 19 21:19:35 2011
@@ -1073,7 +1073,8 @@
   assert((Name || isInstField) && "No identifier for non-field ?");
 
   if (Init)
-    AddInitializerToDecl(Member, Init, false);
+    AddInitializerToDecl(Member, Init, false,
+                         DS.getTypeSpecType() == DeclSpec::TST_auto);
   if (Deleted) // FIXME: Source location is not very good.
     SetDeclDeleted(Member, D.getSourceRange().getBegin());
 
@@ -5953,7 +5954,8 @@
 void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
                                          SourceLocation LParenLoc,
                                          MultiExprArg Exprs,
-                                         SourceLocation RParenLoc) {
+                                         SourceLocation RParenLoc,
+                                         bool TypeMayContainAuto) {
   assert(Exprs.size() != 0 && Exprs.get() && "missing expressions");
 
   // If there is no declaration, there was an error parsing it.  Just ignore
@@ -5968,6 +5970,37 @@
     return;
   }
 
+  // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+  if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) {
+    VDecl->setParsingAutoInit(false);
+
+    // FIXME: n3225 doesn't actually seem to indicate this is ill-formed
+    if (Exprs.size() > 1) {
+      Diag(Exprs.get()[1]->getSourceRange().getBegin(),
+           diag::err_auto_var_init_multiple_expressions)
+        << VDecl->getDeclName() << VDecl->getType()
+        << VDecl->getSourceRange();
+      RealDecl->setInvalidDecl();
+      return;
+    }
+
+    Expr *Init = Exprs.get()[0];
+    QualType DeducedType;
+    if (!DeduceAutoType(VDecl->getType(), Init, DeducedType)) {
+      Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+        << VDecl->getDeclName() << VDecl->getType() << Init->getType()
+        << Init->getSourceRange();
+      RealDecl->setInvalidDecl();
+      return;
+    }
+    VDecl->setType(DeducedType);
+
+    // If this is a redeclaration, check that the type we just deduced matches
+    // the previously declared type.
+    if (VarDecl *Old = VDecl->getPreviousDeclaration())
+      MergeVarDeclTypes(VDecl, Old);
+  }
+
   // 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);

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Feb 19 21:19:35 2011
@@ -75,6 +75,15 @@
     }
   }
 
+  // See if this is an auto-typed variable whose initializer we are parsing.
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (VD->isParsingAutoInit()) {
+      Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
+        << D->getDeclName();
+      return true;
+    }
+  }
+
   // See if the decl is deprecated.
   if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
     EmitDeprecationWarning(D, DA->getMessage(), Loc, UnknownObjCClass);
@@ -964,13 +973,6 @@
 Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
                        const DeclarationNameInfo &NameInfo,
                        const CXXScopeSpec *SS) {
-  if (Ty == Context.UndeducedAutoTy) {
-    Diag(NameInfo.getLoc(),
-         diag::err_auto_variable_cannot_appear_in_own_initializer)
-      << D->getDeclName();
-    return ExprError();
-  }
-
   MarkDeclarationReferenced(NameInfo.getLoc(), D);
 
   Expr *E = DeclRefExpr::Create(Context,
@@ -9650,26 +9652,18 @@
   if (!BT || !BT->isPlaceholderType()) return Owned(E);
 
   // If this is overload, check for a single overload.
-  if (BT->getKind() == BuiltinType::Overload) {
-    if (FunctionDecl *Specialization
-          = ResolveSingleFunctionTemplateSpecialization(E)) {
-      // The access doesn't really matter in this case.
-      DeclAccessPair Found = DeclAccessPair::make(Specialization,
-                                                  Specialization->getAccess());
-      E = FixOverloadedFunctionReference(E, Found, Specialization);
-      if (!E) return ExprError();
-      return Owned(E);
-    }
+  assert(BT->getKind() == BuiltinType::Overload);
 
-    Diag(Loc, diag::err_ovl_unresolvable) << E->getSourceRange();
-    return ExprError();
+  if (FunctionDecl *Specialization
+        = ResolveSingleFunctionTemplateSpecialization(E)) {
+    // The access doesn't really matter in this case.
+    DeclAccessPair Found = DeclAccessPair::make(Specialization,
+                                                Specialization->getAccess());
+    E = FixOverloadedFunctionReference(E, Found, Specialization);
+    if (!E) return ExprError();
+    return Owned(E);
   }
 
-  // Otherwise it's a use of undeduced auto.
-  assert(BT->getKind() == BuiltinType::UndeducedAuto);
-
-  DeclRefExpr *DRE = cast<DeclRefExpr>(E->IgnoreParens());
-  Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
-    << DRE->getDecl() << E->getSourceRange();
+  Diag(Loc, diag::err_ovl_unresolvable) << E->getSourceRange();
   return ExprError();
 }

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Feb 19 21:19:35 2011
@@ -759,11 +759,16 @@
                   Declarator &D, SourceLocation ConstructorLParen,
                   MultiExprArg ConstructorArgs,
                   SourceLocation ConstructorRParen) {
+  bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+
   Expr *ArraySize = 0;
   // If the specified type is an array, unwrap it and save the expression.
   if (D.getNumTypeObjects() > 0 &&
       D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
     DeclaratorChunk &Chunk = D.getTypeObject(0);
+    if (TypeContainsAuto)
+      return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto)
+        << D.getSourceRange());
     if (Chunk.Arr.hasStatic)
       return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new)
         << D.getSourceRange());
@@ -793,14 +798,12 @@
     }
   }
 
-  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0);
+  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0, /*OwnedDecl=*/0,
+                                               /*AllowAuto=*/true);
   QualType AllocType = TInfo->getType();
   if (D.isInvalidType())
     return ExprError();
 
-  if (!TInfo)
-    TInfo = Context.getTrivialTypeSourceInfo(AllocType);
-
   return BuildCXXNew(StartLoc, UseGlobal,
                      PlacementLParen,
                      move(PlacementArgs),
@@ -811,7 +814,8 @@
                      ArraySize,
                      ConstructorLParen,
                      move(ConstructorArgs),
-                     ConstructorRParen);
+                     ConstructorRParen,
+                     TypeContainsAuto);
 }
 
 ExprResult
@@ -825,9 +829,33 @@
                   Expr *ArraySize,
                   SourceLocation ConstructorLParen,
                   MultiExprArg ConstructorArgs,
-                  SourceLocation ConstructorRParen) {
+                  SourceLocation ConstructorRParen,
+                  bool TypeMayContainAuto) {
   SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange();
 
+  // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
+  if (TypeMayContainAuto && AllocType->getContainedAutoType()) {
+    if (ConstructorArgs.size() == 0)
+      return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
+                       << AllocType << TypeRange);
+    if (ConstructorArgs.size() != 1) {
+      Expr *FirstBad = ConstructorArgs.get()[1];
+      return ExprError(Diag(FirstBad->getSourceRange().getBegin(),
+                            diag::err_auto_new_ctor_multiple_expressions)
+                       << AllocType << TypeRange);
+    }
+    QualType DeducedType;
+    if (!DeduceAutoType(AllocType, ConstructorArgs.get()[0], DeducedType))
+      return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
+                       << AllocType
+                       << ConstructorArgs.get()[0]->getType()
+                       << TypeRange
+                       << ConstructorArgs.get()[0]->getSourceRange());
+
+    AllocType = DeducedType;
+    AllocTypeInfo = Context.getTrivialTypeSourceInfo(AllocType, StartLoc);
+  }
+  
   // Per C++0x [expr.new]p5, the type being constructed may be a
   // typedef of an array type.
   if (!ArraySize) {

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat Feb 19 21:19:35 2011
@@ -2783,6 +2783,10 @@
   return false;
 }
 
+bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) {
+  return Visit(T->getDeducedType());
+}
+
 bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
   return VisitTagDecl(T->getDecl());
 }

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Sat Feb 19 21:19:35 2011
@@ -22,6 +22,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "llvm/ADT/BitVector.h"
+#include "TreeTransform.h"
 #include <algorithm>
 
 namespace clang {
@@ -2445,21 +2446,22 @@
     ParamType = ParamType.getLocalUnqualifiedType();
   const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
   if (ParamRefType) {
+    QualType PointeeType = ParamRefType->getPointeeType();
+
     //   [C++0x] If P is an rvalue reference to a cv-unqualified
     //   template parameter and the argument is an lvalue, the type
     //   "lvalue reference to A" is used in place of A for type
     //   deduction.
-    if (const RValueReferenceType *RValueRef
-                                   = dyn_cast<RValueReferenceType>(ParamType)) {
-      if (!RValueRef->getPointeeType().getQualifiers() &&
-          isa<TemplateTypeParmType>(RValueRef->getPointeeType()) &&
+    if (isa<RValueReferenceType>(ParamType)) {
+      if (!PointeeType.getQualifiers() &&
+          isa<TemplateTypeParmType>(PointeeType) &&
           Arg->Classify(S.Context).isLValue())
         ArgType = S.Context.getLValueReferenceType(ArgType);
     }
 
     //   [...] If P is a reference type, the type referred to by P is used
     //   for type deduction.
-    ParamType = ParamRefType->getPointeeType();
+    ParamType = PointeeType;
   }
 
   // Overload sets usually make this parameter an undeduced
@@ -2946,6 +2948,95 @@
                                  QualType(), Specialization, Info);
 }
 
+namespace {
+  /// Substitute the 'auto' type specifier within a type for a given replacement
+  /// type.
+  class SubstituteAutoTransform :
+    public TreeTransform<SubstituteAutoTransform> {
+    QualType Replacement;
+  public:
+    SubstituteAutoTransform(Sema &SemaRef, QualType Replacement) :
+      TreeTransform<SubstituteAutoTransform>(SemaRef), Replacement(Replacement) {
+    }
+    QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) {
+      // If we're building the type pattern to deduce against, don't wrap the
+      // substituted type in an AutoType. Certain template deduction rules
+      // apply only when a template type parameter appears directly (and not if
+      // the parameter is found through desugaring). For instance:
+      //   auto &&lref = lvalue;
+      // must transform into "rvalue reference to T" not "rvalue reference to
+      // auto type deduced as T" in order for [temp.deduct.call]p3 to apply.
+      if (isa<TemplateTypeParmType>(Replacement)) {
+        QualType Result = Replacement;
+        TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
+        NewTL.setNameLoc(TL.getNameLoc());
+        return Result;
+      } else {
+        QualType Result = RebuildAutoType(Replacement);
+        AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
+        NewTL.setNameLoc(TL.getNameLoc());
+        return Result;
+      }
+    }
+  };
+}
+
+/// \brief Deduce the type for an auto type-specifier (C++0x [dcl.spec.auto]p6)
+///
+/// \param Type the type pattern using the auto type-specifier.
+///
+/// \param Init the initializer for the variable whose type is to be deduced.
+///
+/// \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.
+///
+/// \returns true if deduction succeeded, false if it failed.
+bool
+Sema::DeduceAutoType(QualType Type, Expr *Init, QualType &Result) {
+  if (Init->isTypeDependent()) {
+    Result = Type;
+    return true;
+  }
+
+  SourceLocation Loc = Init->getExprLoc();
+
+  LocalInstantiationScope InstScope(*this);
+
+  // Build template<class TemplParam> void Func(FuncParam);
+  NamedDecl *TemplParam
+    = TemplateTypeParmDecl::Create(Context, 0, Loc, 0, 0, 0, false, false);
+  TemplateParameterList *TemplateParams
+    = TemplateParameterList::Create(Context, Loc, Loc, &TemplParam, 1, Loc);
+
+  QualType TemplArg = Context.getTemplateTypeParmType(0, 0, false);
+  QualType FuncParam =
+    SubstituteAutoTransform(*this, TemplArg).TransformType(Type);
+
+  // Deduce type of TemplParam in Func(Init)
+  llvm::SmallVector<DeducedTemplateArgument, 1> Deduced;
+  Deduced.resize(1);
+  QualType InitType = Init->getType();
+  unsigned TDF = 0;
+  if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams,
+                                                FuncParam, InitType, Init,
+                                                TDF))
+    return false;
+
+  TemplateDeductionInfo Info(Context, Loc);
+  if (::DeduceTemplateArguments(*this, TemplateParams,
+                                FuncParam, InitType, Info, Deduced,
+                                TDF))
+    return false;
+
+  QualType DeducedType = Deduced[0].getAsType();
+  if (DeducedType.isNull())
+    return false;
+
+  Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type);
+  return true;
+}
+
 static void
 MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
                            bool OnlyDeduced,
@@ -3740,6 +3831,11 @@
                                OnlyDeduced, Depth, Used);
     break;
 
+  case Type::Auto:
+    MarkUsedTemplateParameters(SemaRef,
+                               cast<AutoType>(T)->getDeducedType(),
+                               OnlyDeduced, Depth, Used);
+
   // None of these types have any template parameters in them.
   case Type::Builtin:
   case Type::VariableArray:

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Feb 19 21:19:35 2011
@@ -324,19 +324,21 @@
     ASTOwningVector<Expr*> InitArgs(SemaRef);
     if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc,
                                 InitArgs, RParenLoc)) {
+      bool TypeMayContainAuto = true;
       // Attach the initializer to the declaration, if we have one.
       if (InitArgs.size() == 0)
-        SemaRef.ActOnUninitializedDecl(Var, false);    
+        SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
       else if (D->hasCXXDirectInitializer()) {
         // Add the direct initializer to the declaration.
         SemaRef.AddCXXDirectInitializerToDecl(Var,
                                               LParenLoc,
                                               move_arg(InitArgs),
-                                              RParenLoc);
+                                              RParenLoc,
+                                              TypeMayContainAuto);
       } else {
         assert(InitArgs.size() == 1);
         Expr *Init = InitArgs.take()[0];
-        SemaRef.AddInitializerToDecl(Var, Init, false);
+        SemaRef.AddInitializerToDecl(Var, Init, false, TypeMayContainAuto);
       }
     } else {
       // FIXME: Not too happy about invalidating the declaration

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Feb 19 21:19:35 2011
@@ -791,7 +791,7 @@
   }
   case DeclSpec::TST_auto: {
     // TypeQuals handled by caller.
-    Result = Context.UndeducedAutoTy;
+    Result = Context.getAutoType(QualType());
     break;
   }
 
@@ -1091,9 +1091,9 @@
     return QualType();
   }
 
-  if (Context.getCanonicalType(T) == Context.UndeducedAutoTy) {
-    Diag(Loc,  diag::err_illegal_decl_array_of_auto)
-      << getPrintableNameForEntity(Entity);
+  if (T->getContainedAutoType()) {
+    Diag(Loc, diag::err_illegal_decl_array_of_auto)
+      << getPrintableNameForEntity(Entity) << T;
     return QualType();
   }
 
@@ -1405,7 +1405,8 @@
 /// The result of this call will never be null, but the associated
 /// type may be a null type if there's an unrecoverable error.
 TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
-                                           TagDecl **OwnedDecl) {
+                                           TagDecl **OwnedDecl,
+                                           bool AutoAllowedInTypeName) {
   // Determine the type of the declarator. Not all forms of declarator
   // have a type.
   QualType T;
@@ -1449,33 +1450,8 @@
   if (D.getAttributes())
     distributeTypeAttrsFromDeclarator(state, T);
 
-  // Check for auto functions and trailing return type and adjust the
-  // return type accordingly.
-  if (getLangOptions().CPlusPlus0x && D.isFunctionDeclarator()) {
-    const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
-    if (T == Context.UndeducedAutoTy) {
-      if (FTI.TrailingReturnType) {
-          T = GetTypeFromParser(ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
-                                &ReturnTypeInfo);
-      }
-      else {
-          Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
-               diag::err_auto_missing_trailing_return);
-          T = Context.IntTy;
-          D.setInvalidType(true);
-      }
-    }
-    else if (FTI.TrailingReturnType) {
-      Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
-           diag::err_trailing_return_without_auto);
-      D.setInvalidType(true);
-    }
-  }
-
-  if (T.isNull())
-    return Context.getNullTypeSourceInfo();
-
-  if (T == Context.UndeducedAutoTy) {
+  if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+      !D.isFunctionDeclarator()) {
     int Error = -1;
 
     switch (D.getContext()) {
@@ -1500,14 +1476,19 @@
       Error = 5; // Template parameter
       break;
     case Declarator::BlockLiteralContext:
-      Error = 6;  // Block literal
+      Error = 6; // Block literal
+      break;
+    case Declarator::TemplateTypeArgContext:
+      Error = 7; // Template type argument
+      break;
+    case Declarator::TypeNameContext:
+      if (!AutoAllowedInTypeName)
+        Error = 8; // Generic
       break;
     case Declarator::FileContext:
     case Declarator::BlockContext:
     case Declarator::ForContext:
     case Declarator::ConditionContext:
-    case Declarator::TypeNameContext:
-    case Declarator::TemplateTypeArgContext:
       break;
     }
 
@@ -1519,6 +1500,9 @@
     }
   }
 
+  if (T.isNull())
+    return Context.getNullTypeSourceInfo();
+
   // The name we're declaring, if any.
   DeclarationName Name;
   if (D.getIdentifier())
@@ -1631,6 +1615,32 @@
         D.setInvalidType(true);
       }
 
+      // Check for auto functions and trailing return type and adjust the
+      // return type accordingly.
+      if (!D.isInvalidType()) {
+        // trailing-return-type is only required if we're declaring a function,
+        // and not, for instance, a pointer to a function.
+        if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+            !FTI.TrailingReturnType && chunkIndex == 0) {
+          Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+               diag::err_auto_missing_trailing_return);
+          T = Context.IntTy;
+          D.setInvalidType(true);
+        } else if (FTI.TrailingReturnType) {
+          if (T.hasQualifiers() || !isa<AutoType>(T)) {
+            // T must be exactly 'auto' at this point. See CWG issue 681.
+            Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
+                 diag::err_trailing_return_without_auto)
+              << T << D.getDeclSpec().getSourceRange();
+            D.setInvalidType(true);
+          }
+
+          T = GetTypeFromParser(
+            ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
+            &ReturnTypeInfo);
+        }
+      }
+
       // cv-qualifiers on return types are pointless except when the type is a
       // class type in C++.
       if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Sat Feb 19 21:19:35 2011
@@ -676,6 +676,13 @@
   /// Subclasses may override this routine to provide different behavior.
   QualType RebuildDecltypeType(Expr *Underlying, SourceLocation Loc);
 
+  /// \brief Build a new C++0x auto type.
+  ///
+  /// By default, builds a new AutoType with the given deduced type.
+  QualType RebuildAutoType(QualType Deduced) {
+    return SemaRef.Context.getAutoType(Deduced);
+  }
+
   /// \brief Build a new template specialization type.
   ///
   /// By default, performs semantic analysis when building the template
@@ -3951,6 +3958,31 @@
 }
 
 template<typename Derived>
+QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
+                                                   AutoTypeLoc TL) {
+  const AutoType *T = TL.getTypePtr();
+  QualType OldDeduced = T->getDeducedType();
+  QualType NewDeduced;
+  if (!OldDeduced.isNull()) {
+    NewDeduced = getDerived().TransformType(OldDeduced);
+    if (NewDeduced.isNull())
+      return QualType();
+  }
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced) {
+    Result = getDerived().RebuildAutoType(NewDeduced);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
+template<typename Derived>
 QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
                                                      RecordTypeLoc TL) {
   const RecordType *T = TL.getTypePtr();

Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.cpp Sat Feb 19 21:19:35 2011
@@ -54,9 +54,6 @@
   case BuiltinType::ObjCId:     ID = PREDEF_TYPE_OBJC_ID;       break;
   case BuiltinType::ObjCClass:  ID = PREDEF_TYPE_OBJC_CLASS;    break;
   case BuiltinType::ObjCSel:    ID = PREDEF_TYPE_OBJC_SEL;      break;
-  case BuiltinType::UndeducedAuto:
-    assert(0 && "Should not see undeduced auto here");
-    break;
   }
 
   return TypeIdx(ID);

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Sat Feb 19 21:19:35 2011
@@ -3146,6 +3146,9 @@
   case TYPE_DECLTYPE:
     return Context->getDecltypeType(ReadExpr(*Loc.F));
 
+  case TYPE_AUTO:
+    return Context->getAutoType(GetType(Record[0]));
+
   case TYPE_RECORD: {
     if (Record.size() != 2) {
       Error("incorrect encoding of record type");
@@ -3457,6 +3460,9 @@
 void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
   TL.setNameLoc(ReadSourceLocation(Record, Idx));
 }
+void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
+  TL.setNameLoc(ReadSourceLocation(Record, Idx));
+}
 void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
   TL.setNameLoc(ReadSourceLocation(Record, Idx));
 }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Sat Feb 19 21:19:35 2011
@@ -213,6 +213,11 @@
   Code = TYPE_DECLTYPE;
 }
 
+void ASTTypeWriter::VisitAutoType(const AutoType *T) {
+  Writer.AddTypeRef(T->getDeducedType(), Record);
+  Code = TYPE_AUTO;
+}
+
 void ASTTypeWriter::VisitTagType(const TagType *T) {
   Record.push_back(T->isDependentType());
   Writer.AddDeclRef(T->getDecl(), Record);
@@ -477,6 +482,9 @@
 void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }
+void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
 void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp Sat Feb 19 21:19:35 2011
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
 void f() {
   auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}}
+  auto *b = b; // expected-error{{variable 'b' declared with 'auto' type cannot appear in its own initializer}}
+  const auto c = c; // expected-error{{variable 'c' declared with 'auto' type cannot appear in its own initializer}}
 }
 
 void g() {
@@ -8,3 +10,32 @@
   
   auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}}
 }
+
+auto n(1,2,3); // expected-error{{initializer for variable 'n' with type 'auto' contains multiple expressions}}
+
+namespace N
+{
+  auto a = "const char [16]", *p = &a;
+}
+
+void h() {
+  auto b = 42ULL;
+
+  for (auto c = 0; c < 100; ++c) {
+  }
+}
+
+template<typename T, typename U> struct same;
+template<typename T> struct same<T, T> {};
+
+void p3example() {
+  auto x = 5;
+  const auto *v = &x, u = 6;
+  static auto y = 0.0;
+  auto int r; // expected-error{{cannot combine with previous}} expected-error{{requires an initializer}}
+
+  same<decltype(x), int> xHasTypeInt;
+  same<decltype(v), const int*> vHasTypeConstIntPtr;
+  same<decltype(u), const int> uHasTypeConstInt;
+  same<decltype(y), double> yHasTypeDouble;
+}

Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp?rev=126069&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp Sat Feb 19 21:19:35 2011
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+
+template<typename T>
+struct only {
+  only(T);
+  template<typename U> only(U) = delete;
+};
+
+void f() {
+  if (auto a = true) {
+  }
+
+  switch (auto a = 0) {
+  }
+
+  while (auto a = false) {
+  }
+
+  for (; auto a = false; ) {
+  }
+
+  new const auto (0);
+  new (auto) (0.0);
+
+#if 0
+  // When clang supports for-range:
+  for (auto i : {1,2,3}) {
+  }
+
+  // When clang supports inline initialization of members.
+  class X {
+    static const auto &n = 'x';
+  };
+#endif
+}

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp Sat Feb 19 21:19:35 2011
@@ -1,13 +1,72 @@
 // RUN: %clang_cc1 -fexceptions -fsyntax-only -verify %s -std=c++0x
-void f() {
-  auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}}
+
+struct S {
+  virtual ~S();
+
+  auto a; // expected-error{{'auto' not allowed in struct member}}
+  auto *b; // expected-error{{'auto' not allowed in struct member}}
+  const auto c; // expected-error{{'auto' not allowed in struct member}}
+
+  void f() throw (auto); // expected-error{{'auto' not allowed here}}
+
+  friend auto; // expected-error{{'auto' not allowed in struct member}}
+
+  operator auto(); // expected-error{{'auto' not allowed here}}
+};
+
+void g(auto a) { // expected-error{{'auto' not allowed in function prototype}}
+  try { }
+  catch (auto &a) { } // expected-error{{'auto' not allowed in exception declaration}}
+  catch (const auto a) { } // expected-error{{'auto' not allowed in exception declaration}}
+  try { } catch (auto a) { } // expected-error{{'auto' not allowed in exception declaration}}
+}
+
+void h(auto a[10]) { // expected-error{{'auto' not allowed in function prototype}}
 }
 
-struct S { auto a; }; // expected-error{{'auto' not allowed in struct member}}
+void i(const auto a) { // expected-error{{'auto' not allowed in function prototype}}
+}
 
-void f(auto a) // expected-error{{'auto' not allowed in function prototype}}
-{
-  try { } catch (auto a) {  } // expected-error{{'auto' not allowed in exception declaration}}
+namespace std {
+  class type_info;
+}
+
+template<typename T> struct U {};
+
+void j() {
+  (void)typeid(auto); // expected-error{{'auto' not allowed here}}
+  (void)sizeof(auto); // expected-error{{'auto' not allowed here}}
+  (void)__alignof(auto); // expected-error{{'auto' not allowed here}}
+
+  // FIXME: don't issue the second diagnostic for this error.
+  U<auto> v; // expected-error{{'auto' not allowed in template argument}} unexpected-error{{C++ requires a type specifier}}
+
+  int n;
+  (void)dynamic_cast<auto&>(S()); // expected-error{{'auto' not allowed here}}
+  (void)static_cast<auto*>(&n); // expected-error{{'auto' not allowed here}}
+  (void)reinterpret_cast<auto*>(&n); // expected-error{{'auto' not allowed here}}
+  (void)const_cast<auto>(n); // expected-error{{'auto' not allowed here}}
+  (void)*(auto*)(&n); // expected-error{{'auto' not allowed here}}
+  (void)auto(n); // expected-error{{expected expression}}
+  (void)auto{n}; // expected-error{{expected expression}}
 }
 
 template <auto a = 10> class C { }; // expected-error{{'auto' not allowed in template parameter}}
+int ints[] = {1, 2, 3};
+template <const auto (*a)[3] = &ints> class D { }; // expected-error{{'auto' not allowed in template parameter}}
+enum E : auto {}; // expected-error{{'auto' not allowed here}}
+struct F : auto {}; // expected-error{{expected class name}}
+template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed here}}
+
+using A = auto; // expected-error{{expected ';'}} expected-error{{requires a qualified name}}
+
+// Whether this is illegal depends on the interpretation of [decl.spec.auto]p2 and p3,
+// and in particular the "Otherwise, ..." at the start of p3.
+namespace TrailingReturnType {
+  // FIXME: don't issue the second diagnostic for this error.
+  auto f() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}}
+  int g();
+  auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}}
+  auto (*i)() = &g; // ok; auto deduced as int.
+  auto (*j)() -> int = i; // ok; no deduction.
+}

Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp?rev=126069&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp Sat Feb 19 21:19:35 2011
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+
+template<typename T>
+struct only {
+  only(T);
+  template<typename U> only(U) = delete;
+};
+
+namespace N
+{
+  auto a = "const char [16]", *p = &a;
+
+  only<const char [16]> testA = a;
+  only<const char **> testP = p;
+}
+
+void h() {
+  auto b = 42ULL;
+  only<unsigned long long> testB = b;
+
+  for (auto c = 0; c < 100; ++c) {
+    only<int> testC = c;
+  }
+}
+
+void p3example() {
+  auto x = 5;
+  const auto *v = &x, u = 6;
+  static auto y = 0.0;
+
+  only<int> testX = x;
+  only<const int*> testV = v;
+  only<const int> testU = u;
+  only<double> testY = y;
+}
+
+void f() {
+  if (auto a = true) {
+    only<bool> testA = a;
+  }
+
+  switch (auto a = 0) {
+  case 0:
+    only<int> testA = a;
+  }
+
+  while (auto a = false) {
+    only<bool> testA = a;
+  }
+
+  for (; auto a = "test"; ) {
+    only<const char[5]> testA = a;
+  }
+
+  auto *fail1 = 0; // expected-error {{variable 'fail1' with type 'auto *' has incompatible initializer of type 'int'}}
+  int **p;
+  // FIXME: due to PR9233, we get the wrong diagnostic here.
+  const auto **fail2(p); // desired-error {{variable 'fail2' with type 'auto const **' has incompatible initializer of type 'int **'}} expected-error {{cannot initialize}}
+}
+
+struct S {
+  void f();
+  char g(int);
+  float g(double);
+  int m;
+
+  void test() {
+    auto p1 = &S::f;
+    auto S::*p2 = &S::f;
+    auto (S::*p3)() = &S::f;
+    auto p4 = &S::g; // expected-error {{incompatible initializer of type '<overloaded function type>'}}
+    auto S::*p5 = &S::g; // expected-error {{incompatible initializer of type '<overloaded function type>'}}
+    auto (S::*p6)(int) = &S::g;
+    auto p7 = &S::m;
+    auto S::*p8 = &S::m;
+
+    only<void (S::*)()> test1 = p1;
+    only<void (S::*)()> test2 = p2;
+    only<void (S::*)()> test3 = p3;
+    only<char (S::*)(int)> test6 = p6;
+    only<int (S::*)> test7 = p7;
+    only<int (S::*)> test8 = p8;
+  }
+};
+
+// TODO: if the initializer is a braced-init-list, deduce auto as std::initializer_list<T>.

Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp?rev=126069&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp Sat Feb 19 21:19:35 2011
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+void f() {
+  auto a = 0, b = 0, c = 0;
+  auto d = 0, e = 0.0; // expected-error {{'int' in declaration of 'd' and deduced as 'double' in declaration of 'e'}}
+
+  auto v1 = 0, *p1 = &v1;
+  auto *p2 = 0, v2 = *p2; // expected-error {{incompatible initializer}}
+
+  const int k = 0;
+  auto &f = k, &g = a; // expected-error {{'const int' in declaration of 'f' and deduced as 'int' in declaration of 'g'}}
+
+  typedef int I;
+  I x;
+  auto xa = x, xb = 0;
+
+  auto &&ra1 = a, rb1 = b; // expected-error {{'int &' in declaration of 'ra1' and deduced as 'int' in declaration of 'rb1'}}
+  auto &&ra2 = +a, rb2 = b;
+}
+
+void g() {
+  auto a = 0, (*b)() -> void, c = 0;
+  auto d = 0, (*e)() -> void, f = 0.0; // expected-error {{'auto' deduced as 'int' in declaration of 'd' and deduced as 'double' in declaration of 'f'}}
+}

Modified: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp Sat Feb 19 21:19:35 2011
@@ -3,4 +3,5 @@
 void f() {
   int b[5];
   auto a[5] = b; // expected-error{{'a' declared as array of 'auto'}}
+  auto *c[5] = b; // expected-error{{'c' declared as array of 'auto *'}}
 }

Added: cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp?rev=126069&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp Sat Feb 19 21:19:35 2011
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s 
+
+auto a() -> int; // ok
+const auto b() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto const'}}
+auto *c() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto *'}}

Added: cfe/trunk/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp?rev=126069&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp Sat Feb 19 21:19:35 2011
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+
+template<typename T>
+struct only {
+  only(T);
+  template<typename U> only(U) = delete;
+};
+
+void f() {
+  only<const int*> p = new const auto (0);
+  only<double*> q = new (auto) (0.0);
+
+  new auto; // expected-error{{new expression for type 'auto' requires a constructor argument}}
+  new (const auto)(); // expected-error{{new expression for type 'auto const' requires a constructor argument}}
+  new (auto) (1,2,3); // expected-error{{new expression for type 'auto' contains multiple constructor arguments}}
+}
+
+void p2example() {
+  only<int*> r = new auto(1);
+  auto x = new auto('a');
+
+  only<char*> testX = x;
+}

Modified: cfe/trunk/test/Misc/diag-aka-types.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-aka-types.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/test/Misc/diag-aka-types.cpp (original)
+++ cfe/trunk/test/Misc/diag-aka-types.cpp Sat Feb 19 21:19:35 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++0x
 
 struct X {};
 typedef X foo_t;
@@ -8,3 +8,7 @@
 
 const foo_t &ref = foo_t();
 char c2 = ref; // expected-error{{'const foo_t' (aka 'const X')}}
+
+// deduced auto should not produce an aka.
+auto aut = X();
+char c3 = aut; // expected-error{{from 'X' to 'char'}}

Added: cfe/trunk/test/SemaCXX/dependent-auto.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dependent-auto.cpp?rev=126069&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/dependent-auto.cpp (added)
+++ cfe/trunk/test/SemaCXX/dependent-auto.cpp Sat Feb 19 21:19:35 2011
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+
+template<typename T>
+struct only {
+  only(T);
+  template<typename U> only(U) = delete; // expected-note {{here}}
+};
+
+template<typename ...T>
+void f(T ...t) {
+  auto x(t...); // expected-error {{requires an initializer}} expected-error {{contains multiple expressions}}
+  only<int> check = x;
+}
+
+void g() {
+  f(); // expected-note {{here}}
+  f(0);
+  f(0, 1); // expected-note {{here}}
+}
+
+
+template<typename T>
+bool h(T t) {
+  auto a = t;
+  decltype(a) b;
+  a = a + b;
+
+  auto p = new auto(t);
+
+  only<double*> test = p; // expected-error {{conversion function from 'char *' to 'only<double *>'}}
+  return p;
+}
+
+bool b = h('x'); // expected-note {{here}}

Added: cfe/trunk/test/SemaCXX/redeclared-auto.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/redeclared-auto.cpp?rev=126069&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/redeclared-auto.cpp (added)
+++ cfe/trunk/test/SemaCXX/redeclared-auto.cpp Sat Feb 19 21:19:35 2011
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+
+extern int a;
+auto a = 0; // expected-note 2{{here}}
+auto a = 0; // expected-error {{redefinition}}
+int a = 0; // expected-error {{redefinition}}
+extern auto a; // expected-error {{requires an initializer}}
+
+extern int b; // expected-note {{here}}
+auto b = 0.0; // expected-error {{different type}}
+
+struct S {
+  static int a;
+  static int b; // expected-note {{here}}
+};
+
+auto S::a = 0; // expected-note 2{{here}}
+auto S::a; // expected-error {{redefinition}} expected-error {{requires an initializer}}
+int S::a = 0; // expected-error {{redefinition}}
+
+auto S::b = 0.0; // expected-error {{different type}}
+
+void f() {
+  extern int a;
+  extern auto a; // expected-error {{requires an initializer}}
+}

Modified: cfe/trunk/test/SemaCXX/trailing-return-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/trailing-return-0x.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/trailing-return-0x.cpp (original)
+++ cfe/trunk/test/SemaCXX/trailing-return-0x.cpp Sat Feb 19 21:19:35 2011
@@ -19,7 +19,7 @@
 
 auto g(); // expected-error{{return without trailing return type}}
 
-int h() -> int; // expected-error{{trailing return type without 'auto'}}
+int h() -> int; // expected-error{{trailing return type must specify return type 'auto', not 'int'}}
 
 int x;
 

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Sat Feb 19 21:19:35 2011
@@ -1312,9 +1312,6 @@
   case BuiltinType::Dependent:
     break;
 
-  case BuiltinType::UndeducedAuto: // FIXME: Deserves a cursor?
-    break;
-
   case BuiltinType::ObjCId:
     VisitType = Context.getObjCIdType();
     break;

Modified: cfe/trunk/tools/libclang/CIndexUSRs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexUSRs.cpp?rev=126069&r1=126068&r2=126069&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexUSRs.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexUSRs.cpp Sat Feb 19 21:19:35 2011
@@ -571,7 +571,6 @@
           c = 'n'; break;
         case BuiltinType::Overload:
         case BuiltinType::Dependent:
-        case BuiltinType::UndeducedAuto:
           IgnoreResults = true;
           return;
         case BuiltinType::ObjCId:





More information about the cfe-commits mailing list