summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-02-08 20:39:08 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-02-08 20:39:08 +0000
commitef2cd8f8c30d48a27995c284cf480867dd8caaa5 (patch)
tree0065424d1864164300f9e6847da61b0e630feea2
parenta028b33c7ff5b1c4de61a6e8b9c0734a49b04bd8 (diff)
downloadbcm5719-llvm-ef2cd8f8c30d48a27995c284cf480867dd8caaa5.tar.gz
bcm5719-llvm-ef2cd8f8c30d48a27995c284cf480867dd8caaa5.zip
More fixes for places where 'decltype(auto)' is permitted in the C++ grammar but makes no sense.
llvm-svn: 294509
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/include/clang/Sema/Sema.h3
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp3
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp31
-rw-r--r--clang/test/SemaCXX/cxx1y-deduced-return-type.cpp35
6 files changed, 55 insertions, 22 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a25b959da65..be6922171ad 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1944,6 +1944,8 @@ def err_auto_bitfield : Error<
"cannot pass bit-field as __auto_type initializer in C">;
// C++1y decltype(auto) type
+def err_decltype_auto_invalid : Error<
+ "'decltype(auto)' not allowed here">;
def err_decltype_auto_cannot_be_combined : Error<
"'decltype(auto)' cannot be combined with other type specifiers">;
def err_decltype_auto_function_declarator_not_declaration : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0fb9a5d3d4d..5b317b018a0 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4749,7 +4749,8 @@ public:
ParsedType ObjectType,
bool EnteringContext);
- ParsedType getDestructorType(const DeclSpec& DS, ParsedType ObjectType);
+ ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
+ ParsedType ObjectType);
// Checks that reinterpret casts don't have undefined behavior.
void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index cb42a88e82b..cb56ebb1043 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -2580,7 +2580,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
if (SS.isEmpty() && Tok.is(tok::kw_decltype)) {
DeclSpec DS(AttrFactory);
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
- if (ParsedType Type = Actions.getDestructorType(DS, ObjectType)) {
+ if (ParsedType Type =
+ Actions.getDestructorTypeForDecltype(DS, ObjectType)) {
Result.setDestructorName(TildeLoc, Type, EndLoc);
return false;
}
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f84d14cfa8c..974e09f78d4 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -3728,6 +3728,9 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
} else if (DS.getTypeSpecType() == TST_decltype) {
BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+ } else if (DS.getTypeSpecType() == TST_decltype_auto) {
+ Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
+ return true;
} else {
LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
LookupParsedName(R, S, &SS);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index d51c50c58f3..1185dacc227 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -323,20 +323,31 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
return nullptr;
}
-ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) {
- if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType)
- return nullptr;
- assert(DS.getTypeSpecType() == DeclSpec::TST_decltype
- && "only get destructor types from declspecs");
- QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
- QualType SearchType = GetTypeFromParser(ObjectType);
- if (SearchType->isDependentType() || Context.hasSameUnqualifiedType(SearchType, T)) {
- return ParsedType::make(T);
- }
+ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS,
+ ParsedType ObjectType) {
+ if (DS.getTypeSpecType() == DeclSpec::TST_error)
+ return nullptr;
+ if (DS.getTypeSpecType() == DeclSpec::TST_decltype_auto) {
+ Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
+ return nullptr;
+ }
+
+ assert(DS.getTypeSpecType() == DeclSpec::TST_decltype &&
+ "unexpected type in getDestructorType");
+ QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
+
+ // If we know the type of the object, check that the correct destructor
+ // type was named now; we can give better diagnostics this way.
+ QualType SearchType = GetTypeFromParser(ObjectType);
+ if (!SearchType.isNull() && !SearchType->isDependentType() &&
+ !Context.hasSameUnqualifiedType(T, SearchType)) {
Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch)
<< T << SearchType;
return nullptr;
+ }
+
+ return ParsedType::make(T);
}
bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,
diff --git a/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp b/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp
index a061cf4ddb7..2592e7cf105 100644
--- a/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp
+++ b/clang/test/SemaCXX/cxx1y-deduced-return-type.cpp
@@ -385,16 +385,31 @@ namespace MemberTemplatesWithDeduction {
}
}
-namespace NNS {
- int n;
- decltype(auto) i();
- decltype(n) j();
- struct X {
- // We resolve a wording bug here: 'decltype(auto)::' should not be parsed
- // as a nested-name-specifier.
- friend decltype(auto) ::NNS::i();
- friend decltype(n) ::NNS::j(); // expected-error {{not a class}}
- };
+// We resolve a wording bug here: 'decltype(auto)' should not be modeled as a
+// decltype-specifier, just as a simple-type-specifier. All the extra places
+// where a decltype-specifier can appear make no sense for 'decltype(auto)'.
+namespace DecltypeAutoShouldNotBeADecltypeSpecifier {
+ namespace NNS {
+ int n;
+ decltype(auto) i();
+ decltype(n) j();
+ struct X {
+ friend decltype(auto) ::DecltypeAutoShouldNotBeADecltypeSpecifier::NNS::i();
+ friend decltype(n) ::DecltypeAutoShouldNotBeADecltypeSpecifier::NNS::j(); // expected-error {{not a class}}
+ };
+ }
+
+ namespace Dtor {
+ struct A {};
+ void f(A a) { a.~decltype(auto)(); } // expected-error {{'decltype(auto)' not allowed here}}
+ }
+
+ namespace BaseClass {
+ struct A : decltype(auto) {}; // expected-error {{'decltype(auto)' not allowed here}}
+ struct B {
+ B() : decltype(auto)() {} // expected-error {{'decltype(auto)' not allowed here}}
+ };
+ }
}
namespace CurrentInstantiation {
OpenPOWER on IntegriCloud