diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 2d35b4d99034..aa01b7fdf06f 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -192,6 +192,7 @@ public: QualType VoidPtrTy, NullPtrTy; QualType OverloadTy; QualType DependentTy; + QualType UndeducedAutoTy; ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 225a42382187..321b1f204fcf 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -572,7 +572,10 @@ public: NullPtr, // This is the type of C++0x 'nullptr'. Overload, // This represents the type of an overloaded function declaration. - Dependent // This represents the type of a type-dependent expression. + Dependent, // This represents the type of a type-dependent expression. + + UndeducedAuto // In C++0x, this represents the type of an auto variable + // that has not been deduced yet. }; private: Kind TypeKind; diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h index 10c5ee39ec50..300602e5147c 100644 --- a/clang/include/clang/Parse/DeclSpec.h +++ b/clang/include/clang/Parse/DeclSpec.h @@ -83,6 +83,7 @@ public: TST_typeofType, TST_typeofExpr, TST_decltype, // C++0x decltype + TST_auto, // C++0x auto TST_error // erroneous type }; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 16a62fdd8cdd..12f75ae863a2 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -179,6 +179,10 @@ void ASTContext::InitBuiltinTypes() { // expressions. InitBuiltinType(DependentTy, BuiltinType::Dependent); + // 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); diff --git a/clang/lib/CodeGen/Mangle.cpp b/clang/lib/CodeGen/Mangle.cpp index 24e441a29635..b5ad5acc0162 100644 --- a/clang/lib/CodeGen/Mangle.cpp +++ b/clang/lib/CodeGen/Mangle.cpp @@ -539,6 +539,9 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { 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; } } diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index 808df70df30d..e93219e01d5c 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -1909,6 +1909,9 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { case BuiltinType::NullPtr: ID = pch::PREDEF_TYPE_NULLPTR_ID; break; case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break; case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break; + case BuiltinType::UndeducedAuto: + assert(0 && "Should not see undeduced auto here"); + break; } Record.push_back((ID << 3) | T.getCVRQualifiers()); diff --git a/clang/lib/Parse/DeclSpec.cpp b/clang/lib/Parse/DeclSpec.cpp index d8c6986f9ea6..8b3b2851c1e0 100644 --- a/clang/lib/Parse/DeclSpec.cpp +++ b/clang/lib/Parse/DeclSpec.cpp @@ -173,6 +173,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_typename: return "type-name"; case DeclSpec::TST_typeofType: case DeclSpec::TST_typeofExpr: return "typeof"; + case DeclSpec::TST_auto: return "auto"; } } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c11383c3eca9..b2b2f31dd6ea 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -926,7 +926,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec); break; case tok::kw_auto: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec); + if (getLang().CPlusPlus0x) + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec); + else + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec); break; case tok::kw_register: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 8a0ad089b68f..b58414234438 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -245,6 +245,11 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, Result = Context.getDecltypeType(E); break; } + case DeclSpec::TST_auto: { + // TypeQuals handled by caller. + Result = Context.UndeducedAutoTy; + break; + } case DeclSpec::TST_error: Result = Context.IntTy; diff --git a/clang/test/SemaCXX/auto-cxx0x.cpp b/clang/test/SemaCXX/auto-cxx0x.cpp new file mode 100644 index 000000000000..33156ef23d2e --- /dev/null +++ b/clang/test/SemaCXX/auto-cxx0x.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x +void f() { + auto int a; // expected-error{{cannot combine with previous 'auto' declaration specifier}} + int auto b; // expected-error{{cannot combine with previous 'int' declaration specifier}} +} diff --git a/clang/test/SemaCXX/auto-cxx98.cpp b/clang/test/SemaCXX/auto-cxx98.cpp new file mode 100644 index 000000000000..14670cd69942 --- /dev/null +++ b/clang/test/SemaCXX/auto-cxx98.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++98 +void f() { + auto int a; + int auto b; +}