aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-06-12 01:51:59 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-06-12 01:51:59 +0000
commit54655be65585ed6618fdd7a19fa6c70efc321d3a (patch)
tree6ebcc7a899ed54cc8e0d069ac9186092a92f73b9
parentc7d2e339f9a71a40db7b199082b42fe91e6fa2cb (diff)
If parsing a trailing-return-type fails, don't pretend we didn't have one at
all. Suppresses follow-on errors mentioned in PR13074. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158348 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/DeclSpec.h22
-rw-r--r--lib/Parse/ParseDecl.cpp4
-rw-r--r--lib/Parse/ParseExprCXX.cpp8
-rw-r--r--lib/Sema/DeclSpec.cpp6
-rw-r--r--lib/Sema/SemaDecl.cpp2
-rw-r--r--lib/Sema/SemaType.cpp20
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp3
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp2
-rw-r--r--test/Parser/cxx11-type-specifier.cpp5
9 files changed, 41 insertions, 31 deletions
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 422a17cc25..6b52cd5e91 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -1104,6 +1104,10 @@ struct DeclaratorChunk {
/// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
unsigned DeleteArgInfo : 1;
+ /// HasTrailingReturnType - If this is true, a trailing return type was
+ /// specified.
+ unsigned HasTrailingReturnType : 1;
+
/// When isVariadic is true, the location of the ellipsis in the source.
unsigned EllipsisLoc;
@@ -1154,10 +1158,9 @@ struct DeclaratorChunk {
Expr *NoexceptExpr;
};
- /// TrailingReturnType - If this isn't null, it's the trailing return type
- /// specified. This is actually a ParsedType, but stored as void* to
- /// allow union storage.
- void *TrailingReturnType;
+ /// TrailingReturnType - If HasTrailingReturnType is true, this is the
+ /// trailing return type specified.
+ UnionParsedType TrailingReturnType;
/// freeArgs - reset the argument list to having zero arguments. This is
/// used in various places for error recovery.
@@ -1222,6 +1225,13 @@ struct DeclaratorChunk {
ExceptionSpecificationType getExceptionSpecType() const {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
}
+
+ /// \brief Determine whether this function declarator had a
+ /// trailing-return-type.
+ bool hasTrailingReturnType() const { return HasTrailingReturnType; }
+
+ /// \brief Get the trailing-return-type for this function declarator.
+ ParsedType getTrailingReturnType() const { return TrailingReturnType; }
};
struct BlockPointerTypeInfo : TypeInfoCommon {
@@ -1352,8 +1362,8 @@ struct DeclaratorChunk {
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
- ParsedType TrailingReturnType =
- ParsedType());
+ TypeResult TrailingReturnType =
+ TypeResult());
/// getBlockPointer - Return a DeclaratorChunk for a block.
///
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index ac6378035c..3eeef7bff3 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -4276,7 +4276,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
SmallVector<SourceRange, 2> DynamicExceptionRanges;
ExprResult NoexceptExpr;
ParsedAttributes FnAttrs(AttrFactory);
- ParsedType TrailingReturnType;
+ TypeResult TrailingReturnType;
Actions.ActOnStartFunctionDeclarator();
@@ -4358,7 +4358,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
if (getLangOpts().CPlusPlus0x && Tok.is(tok::arrow)) {
Diag(Tok, diag::warn_cxx98_compat_trailing_return_type);
SourceRange Range;
- TrailingReturnType = ParseTrailingReturnType(Range).get();
+ TrailingReturnType = ParseTrailingReturnType(Range);
if (Range.getEnd().isValid())
EndLoc = Range.getEnd();
}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 68eff7cf5f..1c7b56fd4d 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -792,10 +792,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
MaybeParseCXX0XAttributes(Attr, &DeclEndLoc);
// Parse trailing-return-type[opt].
- ParsedType TrailingReturnType;
+ TypeResult TrailingReturnType;
if (Tok.is(tok::arrow)) {
SourceRange Range;
- TrailingReturnType = ParseTrailingReturnType(Range).get();
+ TrailingReturnType = ParseTrailingReturnType(Range);
if (Range.getEnd().isValid())
DeclEndLoc = Range.getEnd();
}
@@ -838,10 +838,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
}
// Parse the return type, if there is one.
- ParsedType TrailingReturnType;
+ TypeResult TrailingReturnType;
if (Tok.is(tok::arrow)) {
SourceRange Range;
- TrailingReturnType = ParseTrailingReturnType(Range).get();
+ TrailingReturnType = ParseTrailingReturnType(Range);
if (Range.getEnd().isValid())
DeclEndLoc = Range.getEnd();
}
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index 8ea72ca79c..f6764c2999 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -165,7 +165,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
- ParsedType TrailingReturnType) {
+ TypeResult TrailingReturnType) {
DeclaratorChunk I;
I.Kind = Function;
I.Loc = LocalRangeBegin;
@@ -188,7 +188,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
I.Fun.NumExceptions = 0;
I.Fun.Exceptions = 0;
I.Fun.NoexceptExpr = 0;
- I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr();
+ I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() ||
+ TrailingReturnType.isInvalid();
+ I.Fun.TrailingReturnType = TrailingReturnType.get();
// new[] an argument array if needed.
if (NumArgs) {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9ad8c30505..924b0f73d6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5158,7 +5158,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
QualType T = R->getAs<FunctionType>()->getResultType();
DeclaratorChunk &C = D.getTypeObject(0);
if (!T->isVoidType() && C.Fun.NumArgs == 0 && !C.Fun.isVariadic &&
- !C.Fun.TrailingReturnType &&
+ !C.Fun.hasTrailingReturnType() &&
C.Fun.getExceptionSpecType() == EST_None) {
SourceRange ParenRange(C.Loc, C.EndLoc);
Diag(C.Loc, diag::warn_empty_parens_are_function_decl) << ParenRange;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 209c020fff..21af5f4f2e 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1901,7 +1901,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
if (DeclType.Kind == DeclaratorChunk::Function) {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
- if (FTI.TrailingReturnType) {
+ if (FTI.hasTrailingReturnType()) {
Error = -1;
break;
}
@@ -2176,12 +2176,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// 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) {
+ !FTI.hasTrailingReturnType() && chunkIndex == 0) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_auto_missing_trailing_return);
T = Context.IntTy;
D.setInvalidType(true);
- } else if (FTI.TrailingReturnType) {
+ } else if (FTI.hasTrailingReturnType()) {
// T must be exactly 'auto' at this point. See CWG issue 681.
if (isa<ParenType>(T)) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
@@ -2195,10 +2195,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getDeclSpec().getSourceRange();
D.setInvalidType(true);
}
-
- T = S.GetTypeFromParser(
- ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
- &TInfo);
+ T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo);
+ if (T.isNull()) {
+ // An error occurred parsing the trailing return type.
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ }
}
}
@@ -2301,7 +2303,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = FTI.isVariadic;
- EPI.HasTrailingReturn = FTI.TrailingReturnType;
+ EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
EPI.TypeQuals = FTI.TypeQuals;
EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
: FTI.RefQualifierIsLValueRef? RQ_LValue
@@ -3119,7 +3121,7 @@ namespace {
assert(Chunk.Kind == DeclaratorChunk::Function);
TL.setLocalRangeBegin(Chunk.Loc);
TL.setLocalRangeEnd(Chunk.EndLoc);
- TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType);
+ TL.setTrailingReturn(Chunk.Fun.hasTrailingReturnType());
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
index 71f57dcc66..7499829185 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
@@ -64,5 +64,4 @@ template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed
using A = auto; // expected-error{{'auto' not allowed in type alias}}
-// FIXME: don't issue the second diagnostic for this error.
-auto k() -> auto; // expected-error{{'auto' not allowed in function return type}} unexpected-error{{without trailing return type}}
+auto k() -> auto; // expected-error{{'auto' not allowed in function return type}}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
index 680e9124cb..719aeeddeb 100644
--- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp
@@ -4,4 +4,4 @@
// will necessarily be ill-formed as a trailing return type for a function
// definition), and recover with a "type cannot be defined in a trailing return
// type" error.
-auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{expected a type}} expected-error {{without trailing return type}}
+auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{expected a type}}
diff --git a/test/Parser/cxx11-type-specifier.cpp b/test/Parser/cxx11-type-specifier.cpp
index 212ffb407b..c66462a84f 100644
--- a/test/Parser/cxx11-type-specifier.cpp
+++ b/test/Parser/cxx11-type-specifier.cpp
@@ -21,7 +21,4 @@ void f() {
// And for trailing-type-specifier-seq
-// FIXME: Don't treat an ill-formed trailing-return-type the same as no
-// trailing-return-type, and avoid the second diagnostic.
-auto f() -> unknown; // expected-error{{unknown type name 'unknown'}} \
- expected-error{{'auto' return without trailing return type}}
+auto f() -> unknown; // expected-error{{unknown type name 'unknown'}}