diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 60 |
3 files changed, 55 insertions, 8 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 6559ca4f8f3..6214eb5a111 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -349,6 +349,7 @@ public: QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0, TagDecl **OwnedDecl = 0); DeclarationName GetNameForDeclarator(Declarator &D); + bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); QualType ObjCGetTypeForMethodDefinition(DeclPtrTy D); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index abae9f04cc1..8375a68507a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3176,7 +3176,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, 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, Loc, D), + 0, 0, false, false, 0,0,0, Loc, D), SourceLocation()); D.SetIdentifier(&II, Loc); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 01b8aa4fd41..833620b5cfb 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -760,13 +760,17 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip, // function takes no arguments. llvm::SmallVector<QualType, 4> Exceptions; Exceptions.reserve(FTI.NumExceptions); - for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) - Exceptions.push_back( - QualType::getFromOpaquePtr(FTI.Exceptions[ei])); + for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { + QualType ET = QualType::getFromOpaquePtr(FTI.Exceptions[ei].Ty); + // Check that the type is valid for an exception spec, and drop it + // if not. + if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range)) + Exceptions.push_back(ET); + } T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, FTI.TypeQuals, FTI.hasExceptionSpec, FTI.hasAnyExceptionSpec, - FTI.NumExceptions, Exceptions.data()); + Exceptions.size(), Exceptions.data()); } else if (FTI.isVariadic) { // We allow a zero-parameter variadic function in C if the // function is marked with the "overloadable" @@ -843,14 +847,19 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip, llvm::SmallVector<QualType, 4> Exceptions; Exceptions.reserve(FTI.NumExceptions); - for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) - Exceptions.push_back(QualType::getFromOpaquePtr(FTI.Exceptions[ei])); + for(unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { + QualType ET = QualType::getFromOpaquePtr(FTI.Exceptions[ei].Ty); + // Check that the type is valid for an exception spec, and drop it if + // not. + if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range)) + Exceptions.push_back(ET); + } T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), FTI.isVariadic, FTI.TypeQuals, FTI.hasExceptionSpec, FTI.hasAnyExceptionSpec, - FTI.NumExceptions, Exceptions.data()); + Exceptions.size(), Exceptions.data()); } break; } @@ -953,6 +962,43 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip, return T; } +/// CheckSpecifiedExceptionType - Check if the given type is valid in an +/// exception specification. Incomplete types, or pointers to incomplete types +/// other than void are not allowed. +bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) { + // FIXME: This may not correctly work with the fix for core issue 437, + // where a class's own type is considered complete within its body. + + // C++ 15.4p2: A type denoted in an exception-specification shall not denote + // an incomplete type. + if (T->isIncompleteType()) + return Diag(Range.getBegin(), diag::err_incomplete_in_exception_spec) + << Range << T << /*direct*/0; + + // 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; + } else + return false; + + if (T->isIncompleteType() && !T->isVoidType()) + return Diag(Range.getBegin(), diag::err_incomplete_in_exception_spec) + << Range << T << /*indirect*/kind; + + return false; +} + /// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer /// to member to a function with an exception specification. This means that /// it is invalid to add another level of indirection. |