[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