summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-11-11 02:02:15 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-11-11 02:02:15 +0000
commite301ba2b489106cc31b5f3a4e0cd558f90f07cba (patch)
tree545ee49277a4a4dab3f659d9033c04ac8ddec3d1
parenta543f77bdb6db7f7caa9a853843d5f141ff50a05 (diff)
downloadbcm5719-llvm-e301ba2b489106cc31b5f3a4e0cd558f90f07cba.tar.gz
bcm5719-llvm-e301ba2b489106cc31b5f3a4e0cd558f90f07cba.zip
Add support for GCC's '__auto_type' extension, per the GCC manual:
https://gcc.gnu.org/onlinedocs/gcc/Typeof.html Differences from the GCC extension: * __auto_type is also permitted in C++ (but only in places where it could appear in C), allowing its use in headers that might be shared across C and C++, or used from C++98 * __auto_type can be combined with a declarator, as with C++ auto (for instance, "__auto_type *p") * multiple variables can be declared in a single __auto_type declaration, with the C++ semantics (the deduced type must be the same in each case) This patch also adds a missing restriction on applying typeof to a bit-field, which GCC has historically rejected in C (due to lack of clarity as to whether the operand should be promoted). The same restriction also applies to __auto_type in C (in both GCC and Clang). This also fixes PR25449. Patch by Nicholas Allegra! llvm-svn: 252690
-rw-r--r--clang/include/clang/AST/ASTContext.h2
-rw-r--r--clang/include/clang/AST/Type.h34
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td2
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td3
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td26
-rw-r--r--clang/include/clang/Basic/Specifiers.h1
-rw-r--r--clang/include/clang/Basic/TokenKinds.def1
-rw-r--r--clang/include/clang/Sema/DeclSpec.h4
-rw-r--r--clang/lib/AST/ASTContext.cpp10
-rw-r--r--clang/lib/AST/ASTImporter.cpp2
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp6
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp2
-rw-r--r--clang/lib/AST/Type.cpp2
-rw-r--r--clang/lib/AST/TypePrinter.cpp6
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp2
-rw-r--r--clang/lib/Parse/ParseDecl.cpp6
-rw-r--r--clang/lib/Parse/ParseObjc.cpp1
-rw-r--r--clang/lib/Parse/ParseTentative.cpp3
-rw-r--r--clang/lib/Sema/DeclSpec.cpp2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp8
-rw-r--r--clang/lib/Sema/SemaExpr.cpp8
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp12
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp1
-rw-r--r--clang/lib/Sema/SemaType.cpp109
-rw-r--r--clang/lib/Sema/TreeTransform.h8
-rw-r--r--clang/lib/Serialization/ASTReader.cpp4
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp2
-rw-r--r--clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp6
-rw-r--r--clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp2
-rw-r--r--clang/test/Sema/bitfield.c3
-rw-r--r--clang/test/Sema/exprs.c1
-rw-r--r--clang/test/SemaCXX/auto-cxx0x.cpp3
-rw-r--r--clang/test/SemaCXX/cxx98-compat.cpp3
33 files changed, 192 insertions, 93 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 72bbb606df0..a6d97aaec2e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1299,7 +1299,7 @@ public:
UnaryTransformType::UTTKind UKind) const;
/// \brief C++11 deduced auto type.
- QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
+ QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent) const;
/// \brief C++11 deduction pattern for 'auto' type.
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index d080535ba7e..e9aadec8020 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1210,6 +1210,16 @@ enum RefQualifierKind {
RQ_RValue
};
+/// Which keyword(s) were used to create an AutoType.
+enum class AutoTypeKeyword {
+ /// \brief auto
+ Auto,
+ /// \brief decltype(auto)
+ DecltypeAuto,
+ /// \brief __auto_type (GNU extension)
+ GNUAutoType
+};
+
/// The base class of the type hierarchy.
///
/// A central concept with types is that each type always has a canonical
@@ -1428,8 +1438,9 @@ protected:
unsigned : NumTypeBits;
- /// Was this placeholder type spelled as 'decltype(auto)'?
- unsigned IsDecltypeAuto : 1;
+ /// Was this placeholder type spelled as 'auto', 'decltype(auto)',
+ /// or '__auto_type'? AutoTypeKeyword value.
+ unsigned Keyword : 2;
};
union {
@@ -3902,8 +3913,7 @@ public:
/// is no deduced type and an auto type is canonical. In the latter case, it is
/// also a dependent type.
class AutoType : public Type, public llvm::FoldingSetNode {
- AutoType(QualType DeducedType, bool IsDecltypeAuto,
- bool IsDependent)
+ AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent)
: Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
/*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
/*VariablyModified=*/false,
@@ -3911,13 +3921,18 @@ class AutoType : public Type, public llvm::FoldingSetNode {
? false : DeducedType->containsUnexpandedParameterPack()) {
assert((DeducedType.isNull() || !IsDependent) &&
"auto deduced to dependent type");
- AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;
+ AutoTypeBits.Keyword = (unsigned)Keyword;
}
friend class ASTContext; // ASTContext creates these
public:
- bool isDecltypeAuto() const { return AutoTypeBits.IsDecltypeAuto; }
+ bool isDecltypeAuto() const {
+ return getKeyword() == AutoTypeKeyword::DecltypeAuto;
+ }
+ AutoTypeKeyword getKeyword() const {
+ return (AutoTypeKeyword)AutoTypeBits.Keyword;
+ }
bool isSugared() const { return !isCanonicalUnqualified(); }
QualType desugar() const { return getCanonicalTypeInternal(); }
@@ -3932,14 +3947,13 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getDeducedType(), isDecltypeAuto(),
- isDependentType());
+ Profile(ID, getDeducedType(), getKeyword(), isDependentType());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
- bool IsDecltypeAuto, bool IsDependent) {
+ AutoTypeKeyword Keyword, bool IsDependent) {
ID.AddPointer(Deduced.getAsOpaquePtr());
- ID.AddBoolean(IsDecltypeAuto);
+ ID.AddInteger((unsigned)Keyword);
ID.AddBoolean(IsDependent);
}
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 4b94b186cd6..0b030168aaa 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -24,6 +24,7 @@ def : DiagGroup<"aggregate-return">;
def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">;
def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">;
+def GNUAutoType : DiagGroup<"gnu-auto-type">;
def ArrayBounds : DiagGroup<"array-bounds">;
def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">;
def Availability : DiagGroup<"availability">;
@@ -707,6 +708,7 @@ def C99 : DiagGroup<"c99-extensions">;
// A warning group for warnings about GCC extensions.
def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
+ GNUAutoType,
GNUBinaryLiteral, GNUCaseRange,
GNUComplexInteger, GNUCompoundLiteralInitializer,
GNUConditionalOmittedOperand, GNUDesignator,
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index bf0a128a70d..6e7fbde587c 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -299,6 +299,9 @@ def ext_decltype_auto_type_specifier : ExtWarn<
def warn_cxx11_compat_decltype_auto_type_specifier : Warning<
"'decltype(auto)' type specifier is incompatible with C++ standards before "
"C++14">, InGroup<CXXPre14Compat>, DefaultIgnore;
+def ext_auto_type : Extension<
+ "'__auto_type' is a GNU extension">,
+ InGroup<GNUAutoType>;
def ext_for_range : ExtWarn<
"range-based for loop is a C++11 extension">, InGroup<CXX11>;
def warn_cxx98_compat_for_range : Warning<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9b21c61dce3..43062543057 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1664,18 +1664,22 @@ def warn_cxx98_compat_auto_type_specifier : Warning<
"'auto' type specifier is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_auto_variable_cannot_appear_in_own_initializer : Error<
- "variable %0 declared with 'auto' type cannot appear in its own initializer">;
+ "variable %0 declared with %select{'auto'|'decltype(auto)'|'__auto_type'}1 "
+ "type cannot appear in its own initializer">;
def err_illegal_decl_array_of_auto : Error<
"'%0' declared as array of %1">;
def err_new_array_of_auto : Error<
"cannot allocate array of 'auto'">;
def err_auto_not_allowed : Error<
- "%select{'auto'|'decltype(auto)'}0 not allowed %select{in function prototype"
- "|in non-static struct member"
- "|in non-static union member|in non-static class member|in interface member"
+ "%select{'auto'|'decltype(auto)'|'__auto_type'}0 not allowed "
+ "%select{in function prototype"
+ "|in non-static struct member|in struct member"
+ "|in non-static union member|in union member"
+ "|in non-static class member|in interface member"
"|in exception declaration|in template parameter|in block literal"
"|in template argument|in typedef|in type alias|in function return type"
- "|in conversion function type|here|in lambda parameter}1">;
+ "|in conversion function type|here|in lambda parameter"
+ "|in type allocated by 'new'|in K&R-style function parameter}1">;
def err_auto_not_allowed_var_inst : Error<
"'auto' variable template instantiation is not allowed">;
def err_auto_var_requires_init : Error<
@@ -1709,8 +1713,8 @@ def err_auto_var_deduction_failure_from_init_list : Error<
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<
- "'%select{auto|decltype(auto)}0' deduced as %1 in declaration of %2 and "
- "deduced as %3 in declaration of %4">;
+ "'%select{auto|decltype(auto)|__auto_type}0' deduced as %1 in declaration "
+ "of %2 and deduced as %3 in declaration of %4">;
def err_implied_std_initializer_list_not_found : Error<
"cannot deduce type of initializer list because std::initializer_list was "
"not found; include <initializer_list>">;
@@ -1720,6 +1724,10 @@ def warn_dangling_std_initializer_list : Warning<
"array backing the initializer list will be destroyed at the end of "
"%select{the full-expression|the constructor}0">,
InGroup<DiagGroup<"dangling-initializer-list">>;
+def err_auto_init_list_from_c : Error<
+ "cannot use __auto_type with initializer list in C">;
+def err_auto_bitfield : Error<
+ "cannot pass bit-field as __auto_type initializer in C">;
// C++1y decltype(auto) type
def err_decltype_auto_cannot_be_combined : Error<
@@ -4812,8 +4820,8 @@ def err_sizeof_alignof_function_type : Error<
"function type">;
def err_openmp_default_simd_align_expr : Error<
"invalid application of '__builtin_omp_required_simd_align' to an expression, only type is allowed">;
-def err_sizeof_alignof_bitfield : Error<
- "invalid application of '%select{sizeof|alignof}0' to bit-field">;
+def err_sizeof_alignof_typeof_bitfield : Error<
+ "invalid application of '%select{sizeof|alignof|typeof}0' to bit-field">;
def err_alignof_member_of_incomplete_type : Error<
"invalid application of 'alignof' to a field of a class still being defined">;
def err_vecstep_non_scalar_vector_type : Error<
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 47d2f31c0fe..e5f1f834f75 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -64,6 +64,7 @@ namespace clang {
TST_underlyingType, // __underlying_type for C++11
TST_auto, // C++11 auto
TST_decltype_auto, // C++1y decltype(auto)
+ TST_auto_type, // __auto_type extension
TST_unknown_anytype, // __unknown_anytype extension
TST_atomic, // C11 _Atomic
TST_error // erroneous type
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 1e0ec117d07..9252d9947a9 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -384,6 +384,7 @@ KEYWORD(__real , KEYALL)
KEYWORD(__thread , KEYALL)
KEYWORD(__FUNCTION__ , KEYALL)
KEYWORD(__PRETTY_FUNCTION__ , KEYALL)
+KEYWORD(__auto_type , KEYALL)
// GNU Extensions (outside impl-reserved namespace)
KEYWORD(typeof , KEYGNU)
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index f809c58e056..7bce0cdcfcc 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -301,6 +301,7 @@ public:
static const TST TST_decltype_auto = clang::TST_decltype_auto;
static const TST TST_underlyingType = clang::TST_underlyingType;
static const TST TST_auto = clang::TST_auto;
+ static const TST TST_auto_type = clang::TST_auto_type;
static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
static const TST TST_atomic = clang::TST_atomic;
static const TST TST_error = clang::TST_error;
@@ -512,7 +513,8 @@ public:
void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; }
bool containsPlaceholderType() const {
- return TypeSpecType == TST_auto || TypeSpecType == TST_decltype_auto;
+ return (TypeSpecType == TST_auto || TypeSpecType == TST_auto_type ||
+ TypeSpecType == TST_decltype_auto);
}
bool hasTagDefinition() const;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 4009915619d..18240e79d80 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3983,20 +3983,20 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType,
/// getAutoType - Return the uniqued reference to the 'auto' type which has been
/// deduced to the given type, or to the canonical undeduced 'auto' type, or the
/// canonical deduced-but-dependent 'auto' type.
-QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto,
+QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent) const {
- if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent)
+ if (DeducedType.isNull() && Keyword == AutoTypeKeyword::Auto && !IsDependent)
return getAutoDeductType();
// Look in the folding set for an existing type.
void *InsertPos = nullptr;
llvm::FoldingSetNodeID ID;
- AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent);
+ AutoType::Profile(ID, DeducedType, Keyword, IsDependent);
if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(AT, 0);
AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType,
- IsDecltypeAuto,
+ Keyword,
IsDependent);
Types.push_back(AT);
if (InsertPos)
@@ -4036,7 +4036,7 @@ QualType ASTContext::getAtomicType(QualType T) const {
QualType ASTContext::getAutoDeductType() const {
if (AutoDeductTy.isNull())
AutoDeductTy = QualType(
- new (*this, TypeAlignment) AutoType(QualType(), /*decltype(auto)*/false,
+ new (*this, TypeAlignment) AutoType(QualType(), AutoTypeKeyword::Auto,
/*dependent*/false),
0);
return AutoDeductTy;
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index ccc6931a5ff..824cc180109 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -1746,7 +1746,7 @@ QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
return QualType();
}
- return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(),
+ return Importer.getToContext().getAutoType(ToDeduced, T->getKeyword(),
/*IsDependent*/false);
}
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index c3432839c2e..7f2ef495a20 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2653,9 +2653,11 @@ void CXXNameMangler::mangleType(const UnaryTransformType *T) {
void CXXNameMangler::mangleType(const AutoType *T) {
QualType D = T->getDeducedType();
// <builtin-type> ::= Da # dependent auto
- if (D.isNull())
+ if (D.isNull()) {
+ assert(T->getKeyword() != AutoTypeKeyword::GNUAutoType &&
+ "shouldn't need to mangle __auto_type!");
Out << (T->isDecltypeAuto() ? "Dc" : "Da");
- else
+ } else
mangleType(D);
}
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 5c30ae28b34..01e17588feb 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1818,6 +1818,8 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
Out << '?';
mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
Out << '?';
+ assert(AT->getKeyword() != AutoTypeKeyword::GNUAutoType &&
+ "shouldn't need to mangle __auto_type!");
mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>");
Out << '@';
} else {
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 40fe903feab..611218ff917 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -948,7 +948,7 @@ public:
== T->getDeducedType().getAsOpaquePtr())
return QualType(T, 0);
- return Ctx.getAutoType(deducedType, T->isDecltypeAuto(),
+ return Ctx.getAutoType(deducedType, T->getKeyword(),
T->isDependentType());
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 0bb50c6ba81..b4810d63c80 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -835,7 +835,11 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
if (!T->getDeducedType().isNull()) {
printBefore(T->getDeducedType(), OS);
} else {
- OS << (T->isDecltypeAuto() ? "decltype(auto)" : "auto");
+ switch (T->getKeyword()) {
+ case AutoTypeKeyword::Auto: OS << "auto"; break;
+ case AutoTypeKeyword::DecltypeAuto: OS << "decltype(auto)"; break;
+ case AutoTypeKeyword::GNUAutoType: OS << "__auto_type"; break;
+ }
spaceBeforePlaceHolder(OS);
}
}
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index b44a34115ff..8f08828b5f2 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -905,7 +905,7 @@ private:
(!Line.MightBeFunctionDecl || Current.NestingLevel != 0)) {
Contexts.back().FirstStartOfName = &Current;
Current.Type = TT_StartOfName;
- } else if (Current.is(tok::kw_auto)) {
+ } else if (Current.isOneOf(tok::kw_auto, tok::kw___auto_type)) {
AutoFound = true;
} else if (Current.is(tok::arrow) &&
Style.Language == FormatStyle::LK_Java) {
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 51b4eee24e6..cf3189a91a9 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3138,6 +3138,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
PrevSpec, DiagID, Policy);
isStorageClass = true;
break;
+ case tok::kw___auto_type:
+ Diag(Tok, diag::ext_auto_type);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec,
+ DiagID, Policy);
+ break;
case tok::kw_register:
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,
PrevSpec, DiagID, Policy);
@@ -4440,6 +4445,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw___private_extern__:
case tok::kw_static:
case tok::kw_auto:
+ case tok::kw___auto_type:
case tok::kw_register:
case tok::kw___thread:
case tok::kw_thread_local:
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 4ac8f42f136..698c38f9c31 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -1127,6 +1127,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
case tok::kw__Bool:
case tok::kw__Complex:
case tok::kw___alignof:
+ case tok::kw___auto_type:
IdentifierInfo *II = Tok.getIdentifierInfo();
SelectorLoc = ConsumeToken();
return II;
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 9d2a2b931e8..6fbcfd9bd21 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1089,6 +1089,7 @@ public:
/// [GNU] typeof-specifier
/// [GNU] '_Complex'
/// [C++11] 'auto'
+/// [GNU] '__auto_type'
/// [C++11] 'decltype' ( expression )
/// [C++1y] 'decltype' ( 'auto' )
///
@@ -1262,6 +1263,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw_restrict:
case tok::kw__Complex:
case tok::kw___attribute:
+ case tok::kw___auto_type:
return TPResult::True;
// Microsoft
@@ -1515,6 +1517,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
case tok::kw_double:
case tok::kw_void:
case tok::kw___unknown_anytype:
+ case tok::kw___auto_type:
return true;
case tok::kw_auto:
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 05ec5d4abc4..498a375fe1b 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -288,6 +288,7 @@ bool Declarator::isDeclarationOfFunction() const {
switch (DS.getTypeSpecType()) {
case TST_atomic:
case TST_auto:
+ case TST_auto_type:
case TST_bool:
case TST_char:
case TST_char16:
@@ -476,6 +477,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
case DeclSpec::TST_typeofType:
case DeclSpec::TST_typeofExpr: return "typeof";
case DeclSpec::TST_auto: return "auto";
+ case DeclSpec::TST_auto_type: return "__auto_type";
case DeclSpec::TST_decltype: return "(decltype)";
case DeclSpec::TST_decltype_auto: return "decltype(auto)";
case DeclSpec::TST_underlyingType: return "__underlying_type";
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ed86e854894..18d0c3491b1 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -111,6 +111,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
case tok::kw_wchar_t:
case tok::kw_bool:
case tok::kw___underlying_type:
+ case tok::kw___auto_type:
return true;
case tok::annot_typename:
@@ -5765,7 +5766,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewVD = VarDecl::Create(Context, DC, D.getLocStart(),
D.getIdentifierLoc(), II,
R, TInfo, SC);
-
+
+ if (D.getDeclSpec().containsPlaceholderType() && R->getContainedAutoType())
+ ParsingInitForAutoVars.insert(NewVD);
+
if (D.isInvalidType())
NewVD->setInvalidDecl();
} else {
@@ -10243,7 +10247,7 @@ Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group,
} else if (DeducedCanon != UCanon) {
Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
diag::err_auto_different_deductions)
- << (AT->isDecltypeAuto() ? 1 : 0)
+ << (unsigned)AT->getKeyword()
<< Deduced << DeducedDecl->getDeclName()
<< U << D->getDeclName()
<< DeducedDecl->getInit()->getSourceRange()
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a1e2c0191f6..aee3e3c49a9 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -349,8 +349,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D)) {
+ const AutoType *AT = cast<VarDecl>(D)->getType()->getContainedAutoType();
+
Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
- << D->getDeclName();
+ << D->getDeclName() << (unsigned)AT->getKeyword();
return true;
}
@@ -3685,7 +3687,7 @@ static bool CheckAlignOfExpr(Sema &S, Expr *E) {
return false;
if (E->getObjectKind() == OK_BitField) {
- S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield)
+ S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield)
<< 1 << E->getSourceRange();
return true;
}
@@ -3787,7 +3789,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
isInvalid = true;
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
- Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 0;
isInvalid = true;
} else {
isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf);
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 8b2e7db8a24..2605acddfac 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3908,7 +3908,7 @@ namespace {
!Replacement.isNull() && Replacement->isDependentType();
QualType Result =
SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,
- TL.getTypePtr()->isDecltypeAuto(),
+ TL.getTypePtr()->getKeyword(),
Dependent);
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
@@ -3976,6 +3976,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
if (Result.isNull())
return DAR_FailedAlreadyDiagnosed;
return DAR_Succeeded;
+ } else if (!getLangOpts().CPlusPlus) {
+ if (isa<InitListExpr>(Init)) {
+ Diag(Init->getLocStart(), diag::err_auto_init_list_from_c);
+ return DAR_FailedAlreadyDiagnosed;
+ }
}
}
@@ -4013,6 +4018,11 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result) {
return DAR_Failed;
}
} else {
+ if (!getLangOpts().CPlusPlus && Init->refersToBitField()) {
+ Diag(Loc, diag::err_auto_bitfield);
+ return DAR_FailedAlreadyDiagnosed;
+ }
+
if (AdjustFunctionParmAndArgTypesForDeduction(
*this, TemplateParamsSt.get(), FuncParam, InitType, Init, TDF))
return DAR_Failed;
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index a7fef8a29d8..61052f06c83 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -737,6 +737,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_interface:
case TST_class:
case TST_auto:
+ case TST_auto_type:
case TST_decltype_auto:
case TST_unknown_anytype:
case TST_error:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index e53c7792e50..bbd0c3fbd06 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1504,14 +1504,17 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// template type parameter.
Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
} else {
- Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false);
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
}
break;
+ case DeclSpec::TST_auto_type:
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false);
+ break;
+
case DeclSpec::TST_decltype_auto:
- Result = Context.getAutoType(QualType(),
- /*decltype(auto)*/true,
- /*IsDependent*/ false);
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto,
+ /*IsDependent*/ false);
break;
case DeclSpec::TST_unknown_anytype:
@@ -2573,8 +2576,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// The TagDecl owned by the DeclSpec.
TagDecl *OwnedTagDecl = nullptr;
- bool ContainsPlaceholderType = false;
-
switch (D.getName().getKind()) {
case UnqualifiedId::IK_ImplicitSelfParam:
case UnqualifiedId::IK_OperatorFunctionId:
@@ -2582,7 +2583,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
T = ConvertDeclSpecToType(state);
- ContainsPlaceholderType = D.getDeclSpec().containsPlaceholderType();
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
@@ -2606,7 +2606,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// converts to.
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
&ReturnTypeInfo);
- ContainsPlaceholderType = T->getContainedAutoType();
break;
}
@@ -2614,17 +2613,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
distributeTypeAttrsFromDeclarator(state, T);
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
- // In C++11, a function declarator using 'auto' must have a trailing return
- // type (this is checked later) and we can skip this. In other languages
- // using auto, we need to check regardless.
- // C++14 In generic lambdas allow 'auto' in their parameters.
- if (ContainsPlaceholderType &&
- (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
+ if (D.getDeclSpec().containsPlaceholderType()) {
int Error = -1;
switch (D.getContext()) {
- case Declarator::KNRTypeListContext:
- llvm_unreachable("K&R type lists aren't allowed in C++");
case Declarator::LambdaExprContext:
llvm_unreachable("Can't specify a type specifier in lambda grammar");
case Declarator::ObjCParameterContext:
@@ -2633,69 +2625,88 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 0;
break;
case Declarator::LambdaExprParameterContext:
+ // In C++14, generic lambdas allow 'auto' in their parameters.
if (!(SemaRef.getLangOpts().CPlusPlus14
&& D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
- Error = 14;
+ Error = 16;
break;
- case Declarator::MemberContext:
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
+ case Declarator::MemberContext: {
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
+ D.isFunctionDeclarator())
break;
+ bool Cxx = SemaRef.getLangOpts().CPlusPlus;
switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
case TTK_Enum: llvm_unreachable("unhandled tag kind");
- case TTK_Struct: Error = 1; /* Struct member */ break;
- case TTK_Union: Error = 2; /* Union member */ break;
- case TTK_Class: Error = 3; /* Class member */ break;
- case TTK_Interface: Error = 4; /* Interface member */ break;
+ case TTK_Struct: Error = Cxx ? 1 : 2; /* Struct member */ break;
+ case TTK_Union: Error = Cxx ? 3 : 4; /* Union member */ break;
+ case TTK_Class: Error = 5; /* Class member */ break;
+ case TTK_Interface: Error = 6; /* Interface member */ break;
}
break;
+ }
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
- Error = 5; // Exception declaration
+ Error = 7; // Exception declaration
break;
case Declarator::TemplateParamContext:
- Error = 6; // Template parameter
+ Error = 8; // Template parameter
break;
case Declarator::BlockLiteralContext:
- Error = 7; // Block literal
+ Error = 9; // Block literal
break;
case Declarator::TemplateTypeArgContext:
- Error = 8; // Template type argument
+ Error = 10; // Template type argument
break;
case Declarator::AliasDeclContext:
case Declarator::AliasTemplateContext:
- Error = 10; // Type alias
+ Error = 12; // Type alias
break;
case Declarator::TrailingReturnContext:
- if (!SemaRef.getLangOpts().CPlusPlus14)
- Error = 11; // Function return type
+ if (!SemaRef.getLangOpts().CPlusPlus14 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 13; // Function return type
break;
case Declarator::ConversionIdContext:
- if (!SemaRef.getLangOpts().CPlusPlus14)
- Error = 12; // conversion-type-id
+ if (!SemaRef.getLangOpts().CPlusPlus14 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 14; // conversion-type-id
break;
case Declarator::TypeNameContext:
- Error = 13; // Generic
+ Error = 15; // Generic
break;
case Declarator::FileContext:
case Declarator::BlockContext:
case Declarator::ForContext:
case Declarator::ConditionContext:
+ break;
case Declarator::CXXNewContext:
+ if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type)
+ Error = 17; // 'new' type
+ break;
+ case Declarator::KNRTypeListContext:
+ Error = 18; // K&R function parameter
break;
}
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- Error = 9;
-
- // In Objective-C it is an error to use 'auto' on a function declarator.
- if (D.isFunctionDeclarator())
Error = 11;
+ // In Objective-C it is an error to use 'auto' on a function declarator
+ // (and everywhere for '__auto_type').
+ if (D.isFunctionDeclarator() &&
+ (!SemaRef.getLangOpts().CPlusPlus11 ||
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto_type))
+ Error = 13;
+
+ bool HaveTrailing = false;
+
// C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
// contains a trailing return type. That is only legal at the outermost
// level. Check all declarator chunks (outermost first) anyway, to give
// better diagnostics.
- if (SemaRef.getLangOpts().CPlusPlus11 && Error != -1) {
+ // We don't support '__auto_type' with trailing return types.
+ if (SemaRef.getLangOpts().CPlusPlus11 &&
+ D.getDeclSpec().getTypeSpecType() != DeclSpec::TST_auto_type) {
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
@@ -2703,6 +2714,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (DeclType.Kind == DeclaratorChunk::Function) {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
if (FTI.hasTrailingReturnType()) {
+ HaveTrailing = true;
Error = -1;
break;
}
@@ -2715,16 +2727,24 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
- const bool IsDeclTypeAuto =
- D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto;
+ unsigned Keyword;
+ switch (D.getDeclSpec().getTypeSpecType()) {
+ case DeclSpec::TST_auto: Keyword = 0; break;
+ case DeclSpec::TST_decltype_auto: Keyword = 1; break;
+ case DeclSpec::TST_auto_type: Keyword = 2; break;
+ default: llvm_unreachable("unknown auto TypeSpecType");
+ }
SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
- << IsDeclTypeAuto << Error << AutoRange;
+ << Keyword << Error << AutoRange;
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
- } else
+ } else if (!HaveTrailing) {
+ // If there was a trailing return type, we already got
+ // warn_cxx98_compat_trailing_return_type in the parser.
SemaRef.Diag(AutoRange.getBegin(),
diag::warn_cxx98_compat_auto_type_specifier)
<< AutoRange;
+ }
}
if (SemaRef.getLangOpts().CPlusPlus &&
@@ -3729,7 +3749,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
} else if (D.getContext() != Declarator::LambdaExprContext &&
(T.hasQualifiers() || !isa<AutoType>(T) ||
- cast<AutoType>(T)->isDecltypeAuto())) {
+ cast<AutoType>(T)->getKeyword() != AutoTypeKeyword::Auto)) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
@@ -6792,6 +6812,9 @@ QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
if (ER.isInvalid()) return QualType();
E = ER.get();
+ if (!getLangOpts().CPlusPlus && E->refersToBitField())
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
+
if (!E->isTypeDependent()) {
QualType T = E->getType();
if (const TagType *TT = T->getAs<TagType>())
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 12f18c7489d..ca85ad5ea91 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -848,11 +848,11 @@ public:
/// \brief Build a new C++11 auto type.
///
/// By default, builds a new AutoType with the given deduced type.
- QualType RebuildAutoType(QualType Deduced, bool IsDecltypeAuto) {
+ QualType RebuildAutoType(QualType Deduced, AutoTypeKeyword Keyword) {
// Note, IsDependent is always false here: we implicitly convert an 'auto'
// which has been deduced to a dependent type into an undeduced 'auto', so
// that we'll retry deduction after the transformation.
- return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto,
+ return SemaRef.Context.getAutoType(Deduced, Keyword,
/*IsDependent*/ false);
}
@@ -3888,7 +3888,7 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
Qs.removeObjCLifetime();
Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
Qs);
- Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(),
+ Result = SemaRef.Context.getAutoType(Deduced, AutoTy->getKeyword(),
AutoTy->isDependentType());
TLB.TypeWasModifiedSafely(Result);
} else {
@@ -5091,7 +5091,7 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced ||
T->isDependentType()) {
- Result = getDerived().RebuildAutoType(NewDeduced, T->isDecltypeAuto());
+ Result = getDerived().RebuildAutoType(NewDeduced, T->getKeyword());
if (Result.isNull())
return QualType();
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 32656037921..fa84b94b082 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -5413,9 +5413,9 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
case TYPE_AUTO: {
QualType Deduced = readType(*Loc.F, Record, Idx);
- bool IsDecltypeAuto = Record[Idx++];
+ AutoTypeKeyword Keyword = (AutoTypeKeyword)Record[Idx++];
bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;
- return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent);
+ return Context.getAutoType(Deduced, Keyword, IsDependent);
}
case TYPE_RECORD: {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 5508b6eceac..0b257a4a1b0 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -281,7 +281,7 @@ void ASTTypeWriter::VisitUnaryTransformType(const UnaryTransformType *T) {
void ASTTypeWriter::VisitAutoType(const AutoType *T) {
Writer.AddTypeRef(T->getDeducedType(), Record);
- Record.push_back(T->isDecltypeAuto());
+ Record.push_back((unsigned)T->getKeyword());
if (T->getDeducedType().isNull())
Record.push_back(T->isDependentType());
Code = TYPE_AUTO;
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp
index 39c547b9aec..eb751517e2f 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp
@@ -3,9 +3,9 @@
// FIXME: This is in p11 (?) in C++1y.
void f() {
- decltype(auto) a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}}
- if (decltype(auto) b = b) {} // expected-error {{variable 'b' declared with 'auto' type cannot appear in its own initializer}}
- decltype(auto) c = ({ decltype(auto) d = c; 0; }); // expected-error {{variable 'c' declared with 'auto' type cannot appear in its own initializer}}
+ decltype(auto) a = a; // expected-error{{variable 'a' declared with 'decltype(auto)' type cannot appear in its own initializer}}
+ if (decltype(auto) b = b) {} // expected-error {{variable 'b' declared with 'decltype(auto)' type cannot appear in its own initializer}}
+ decltype(auto) c = ({ decltype(auto) d = c; 0; }); // expected-error {{variable 'c' declared with 'decltype(auto)' type cannot appear in its own initializer}}
}
void g() {
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp
index c3dc1de3ed6..06bd72e125d 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp
@@ -49,7 +49,7 @@ decltype(auto) f1();
decltype(auto) (*f2)(); // expected-error {{'decltype(auto)' can only be used as a return type in a function declaration}} expected-error {{requires an initializer}}
decltype(auto) *f3(); // expected-error {{cannot form pointer to 'decltype(auto)'}}
const decltype(auto) f4(); // expected-error {{'decltype(auto)' cannot be combined with other type specifiers}}
-typedef decltype(auto) f5(); // expected-error {{'decltype(auto)' can only be used as a return type in a function declaration}}
+typedef decltype(auto) f5(); // expected-error {{'decltype(auto)' not allowed in typedef}}
decltype(auto) ((((((f6))))())); // ok
decltype(auto) f7()(); // expected-error {{'decltype(auto)' can only be used as a return type in a function declaration}} expected-error {{function cannot return function type}}
decltype(auto) (S::*f8)(); // expected-error {{'decltype(auto)' can only be used as a return type in a function declaration}} expected-error {{requires an initializer}}
diff --git a/clang/test/Sema/bitfield.c b/clang/test/Sema/bitfield.c
index ba8460d3f6c..810dc798eaa 100644
--- a/clang/test/Sema/bitfield.c
+++ b/clang/test/Sema/bitfield.c
@@ -63,7 +63,8 @@ typedef unsigned Unsigned;
typedef signed Signed;
struct Test5 { unsigned n : 2; } t5;
-typedef __typeof__(t5.n) Unsigned; // Bitfield is unsigned
+// Bitfield is unsigned
+struct Test5 sometest5 = {-1}; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -1 to 3}}
typedef __typeof__(+t5.n) Signed; // ... but promotes to signed.
typedef __typeof__(t5.n + 0) Signed; // Arithmetic promotes.
diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c
index 17b1aa2851b..5da4f949a15 100644
--- a/clang/test/Sema/exprs.c
+++ b/clang/test/Sema/exprs.c
@@ -97,6 +97,7 @@ int test9(struct f *P) {
R = __alignof(P->x); // expected-error {{invalid application of 'alignof' to bit-field}}
R = __alignof(P->y); // ok.
R = sizeof(P->x); // expected-error {{invalid application of 'sizeof' to bit-field}}
+ __extension__ ({ R = (__typeof__(P->x)) 2; }); // expected-error {{invalid application of 'typeof' to bit-field}}
return R;
}
diff --git a/clang/test/SemaCXX/auto-cxx0x.cpp b/clang/test/SemaCXX/auto-cxx0x.cpp
index a8f9e84423a..f3daf1a19f3 100644
--- a/clang/test/SemaCXX/auto-cxx0x.cpp
+++ b/clang/test/SemaCXX/auto-cxx0x.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y
void f() {
auto int a; // expected-warning {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
int auto b; // expected-error{{cannot combine with previous 'int' declaration specifier}}
}
+
+typedef auto PR25449(); // expected-error {{'auto' not allowed in typedef}}
diff --git a/clang/test/SemaCXX/cxx98-compat.cpp b/clang/test/SemaCXX/cxx98-compat.cpp
index 4227272d14e..25a086d9bcd 100644
--- a/clang/test/SemaCXX/cxx98-compat.cpp
+++ b/clang/test/SemaCXX/cxx98-compat.cpp
@@ -100,6 +100,9 @@ struct RefQualifier {
};
auto f() -> int; // expected-warning {{trailing return types are incompatible with C++98}}
+#ifdef CXX14COMPAT
+auto ff() { return 5; } // expected-warning {{'auto' type specifier is incompatible with C++98}}
+#endif
void RangeFor() {
int xs[] = {1, 2, 3};
OpenPOWER on IntegriCloud