"deleted definition must be first declaration">;
// C++ exception specifications
+def err_exception_spec_in_typedef : Error<
+ "exception specifications are not allowed in typedefs">;
def err_distant_exception_spec : Error<
"exception specifications are not allowed beyond a single level "
"of indirection">;
def err_incomplete_in_exception_spec : Error<
- "%select{|pointer to |member pointer to |reference to }1incomplete type %0 "
- "is not allowed in exception specification">;
+ "%select{|pointer to |reference to }1incomplete type %0 is not allowed "
+ "in exception specification">;
// C++ access checking
def err_class_redeclared_with_different_access : Error<
/// the function has one.
unsigned NumExceptions;
+ /// ThrowLoc - When hasExceptionSpec is true, the location of the throw
+ /// keyword introducing the spec.
+ unsigned ThrowLoc;
+
/// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
/// describe the arguments for this function declarator. This is null if
/// there are no arguments specified.
SourceLocation getEllipsisLoc() const {
return SourceLocation::getFromRawEncoding(EllipsisLoc);
}
+ SourceLocation getThrowLoc() const {
+ return SourceLocation::getFromRawEncoding(ThrowLoc);
+ }
};
struct BlockPointerTypeInfo {
SourceLocation EllipsisLoc,
ParamInfo *ArgInfo, unsigned NumArgs,
unsigned TypeQuals, bool hasExceptionSpec,
+ SourceLocation ThrowLoc,
bool hasAnyExceptionSpec,
ActionBase::TypeTy **Exceptions,
SourceRange *ExceptionRanges,
unsigned NumArgs,
unsigned TypeQuals,
bool hasExceptionSpec,
+ SourceLocation ThrowLoc,
bool hasAnyExceptionSpec,
ActionBase::TypeTy **Exceptions,
SourceRange *ExceptionRanges,
I.Fun.NumArgs = NumArgs;
I.Fun.ArgInfo = 0;
I.Fun.hasExceptionSpec = hasExceptionSpec;
+ I.Fun.ThrowLoc = ThrowLoc.getRawEncoding();
I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec;
I.Fun.NumExceptions = NumExceptions;
I.Fun.Exceptions = 0;
// cv-qualifier-seq[opt].
DeclSpec DS;
bool hasExceptionSpec = false;
+ SourceLocation ThrowLoc;
bool hasAnyExceptionSpec = false;
llvm::SmallVector<TypeTy*, 2> Exceptions;
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
// Parse exception-specification[opt].
if (Tok.is(tok::kw_throw)) {
hasExceptionSpec = true;
+ ThrowLoc = Tok.getLocation();
ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges,
hasAnyExceptionSpec);
assert(Exceptions.size() == ExceptionRanges.size() &&
SourceLocation(),
/*arglist*/ 0, 0,
DS.getTypeQualifiers(),
- hasExceptionSpec,
+ hasExceptionSpec, ThrowLoc,
hasAnyExceptionSpec,
Exceptions.data(),
ExceptionRanges.data(),
DeclSpec DS;
bool hasExceptionSpec = false;
+ SourceLocation ThrowLoc;
bool hasAnyExceptionSpec = false;
llvm::SmallVector<TypeTy*, 2> Exceptions;
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
// Parse exception-specification[opt].
if (Tok.is(tok::kw_throw)) {
hasExceptionSpec = true;
+ ThrowLoc = Tok.getLocation();
ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges,
hasAnyExceptionSpec);
assert(Exceptions.size() == ExceptionRanges.size() &&
EllipsisLoc,
ParamInfo.data(), ParamInfo.size(),
DS.getTypeQualifiers(),
- hasExceptionSpec,
+ hasExceptionSpec, ThrowLoc,
hasAnyExceptionSpec,
Exceptions.data(),
ExceptionRanges.data(),
SourceLocation(),
&ParamInfo[0], ParamInfo.size(),
/*TypeQuals*/0,
- /*exception*/false, false, 0, 0, 0,
+ /*exception*/false,
+ SourceLocation(), false, 0, 0, 0,
LParenLoc, D),
RLoc);
}
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
SourceLocation(),
0, 0, 0,
- false, false, 0, 0, 0,
+ false, SourceLocation(),
+ false, 0, 0, 0,
CaretLoc, ParamInfo),
CaretLoc);
assert(!Error && "Error setting up implicit decl!");
Declarator D(DS, Declarator::BlockContext);
D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0,
- 0, 0, false, false, 0,0,0, Loc, D),
+ 0, 0, false, SourceLocation(),
+ false, 0,0,0, Loc, D),
SourceLocation());
D.SetIdentifier(&II, Loc);
// does not have a K&R-style identifier list), then the arguments are part
// of the type, otherwise the argument list is ().
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
-
+
// C99 6.7.5.3p1: The return type may not be a function or array type.
if (T->isArrayType() || T->isFunctionType()) {
Diag(DeclType.Loc, diag::err_func_returning_array_function) << T;
<< Context.getTypeDeclType(Tag);
}
+ // Exception specs are not allowed in typedefs. Complain, but add it
+ // anyway.
+ if (FTI.hasExceptionSpec &&
+ D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef);
+
if (FTI.NumArgs == 0) {
if (getLangOptions().CPlusPlus) {
// C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
// C++ 15.4p2: A type denoted in an exception-specification shall not denote
// an incomplete type a pointer or reference to an incomplete type, other
// than (cv) void*.
- // The standard does not mention member pointers, but it has to mean them too.
int kind;
if (const PointerType* IT = T->getAsPointerType()) {
T = IT->getPointeeType();
kind = 1;
- } else if (const MemberPointerType* IT = T->getAsMemberPointerType()) {
- T = IT->getPointeeType();
- kind = 2;
} else if (const ReferenceType* IT = T->getAsReferenceType()) {
T = IT->getPointeeType();
- kind = 3;
+ kind = 2;
} else
return false;
// Function taking reference to function with spec
void g(void pfa() throw(int));
// Typedef for pointer to function with spec
-typedef int (*pf)() throw(int); // xpected-error spec-on-typedef
+typedef int (*pf)() throw(int); // expected-error {{specifications are not allowed in typedefs}}
// Some more:
// Function returning function with spec