diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Sema/SemaExceptionSpec.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r-- | lib/Sema/SemaExceptionSpec.cpp | 116 |
1 files changed, 65 insertions, 51 deletions
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index e1f4888..26c3d35 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -16,9 +16,9 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -38,43 +38,55 @@ static const FunctionProtoType *GetUnderlyingFunction(QualType 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) { - - // This check (and the similar one below) deals with issue 437, that changes - // C++ 9.2p2 this way: - // Within the class member-specification, the class is regarded as complete - // within function bodies, default arguments, exception-specifications, and - // constructor ctor-initializers (including such things in nested classes). - if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) - return false; - - // C++ 15.4p2: A type denoted in an exception-specification shall not denote - // an incomplete type. - if (RequireCompleteType(Range.getBegin(), T, - diag::err_incomplete_in_exception_spec, - /*direct*/0, Range)) - return true; - - // 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*. - int kind; - if (const PointerType* IT = T->getAs<PointerType>()) { - T = IT->getPointeeType(); - kind = 1; - } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) { - T = IT->getPointeeType(); - kind = 2; - } else - return false; +/// +/// \param[in,out] T The exception type. This will be decayed to a pointer type +/// when the input is an array or a function type. +bool Sema::CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range) { + // C++11 [except.spec]p2: + // A type cv T, "array of T", or "function returning T" denoted + // in an exception-specification is adjusted to type T, "pointer to T", or + // "pointer to function returning T", respectively. + // + // We also apply this rule in C++98. + if (T->isArrayType()) + T = Context.getArrayDecayedType(T); + else if (T->isFunctionType()) + T = Context.getPointerType(T); + + int Kind = 0; + QualType PointeeT = T; + if (const PointerType *PT = T->getAs<PointerType>()) { + PointeeT = PT->getPointeeType(); + Kind = 1; + + // cv void* is explicitly permitted, despite being a pointer to an + // incomplete type. + if (PointeeT->isVoidType()) + return false; + } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) { + PointeeT = RT->getPointeeType(); + Kind = 2; + + if (RT->isRValueReferenceType()) { + // C++11 [except.spec]p2: + // A type denoted in an exception-specification shall not denote [...] + // an rvalue reference type. + Diag(Range.getBegin(), diag::err_rref_in_exception_spec) + << T << Range; + return true; + } + } - // Again as before - if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) - return false; - - if (!T->isVoidType() && - RequireCompleteType(Range.getBegin(), T, - diag::err_incomplete_in_exception_spec, kind, Range)) + // C++11 [except.spec]p2: + // A type denoted in an exception-specification shall not denote an + // incomplete type other than a class currently being defined [...]. + // A type denoted in an exception-specification shall not denote a + // pointer or reference to an incomplete type, other than (cv) void* or a + // pointer or reference to a class currently being defined. + if (!(PointeeT->isRecordType() && + PointeeT->getAs<RecordType>()->isBeingDefined()) && + RequireCompleteType(Range.getBegin(), PointeeT, + diag::err_incomplete_in_exception_spec, Kind, Range)) return true; return false; @@ -112,7 +124,7 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { return SourceFPT; // Compute or instantiate the exception specification now. - if (FPT->getExceptionSpecType() == EST_Unevaluated) + if (SourceFPT->getExceptionSpecType() == EST_Unevaluated) EvaluateImplicitExceptionSpec(Loc, cast<CXXMethodDecl>(SourceDecl)); else InstantiateExceptionSpec(Loc, SourceDecl); @@ -159,7 +171,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // If a declaration of a function has an implicit // exception-specification, other declarations of the function shall // not specify an exception-specification. - if (getLangOpts().CPlusPlus0x && + if (getLangOpts().CPlusPlus11 && hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) { Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch) << hasImplicitExceptionSpec(Old); @@ -191,10 +203,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { Old->isExternC()) { FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); EPI.ExceptionSpecType = EST_DynamicNone; - QualType NewType = Context.getFunctionType(NewProto->getResultType(), - NewProto->arg_type_begin(), - NewProto->getNumArgs(), - EPI); + QualType NewType = + Context.getFunctionType(NewProto->getResultType(), + ArrayRef<QualType>(NewProto->arg_type_begin(), + NewProto->getNumArgs()), + EPI); New->setType(NewType); return false; } @@ -215,10 +228,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // Update the type of the function with the appropriate exception // specification. - QualType NewType = Context.getFunctionType(NewProto->getResultType(), - NewProto->arg_type_begin(), - NewProto->getNumArgs(), - EPI); + QualType NewType = + Context.getFunctionType(NewProto->getResultType(), + ArrayRef<QualType>(NewProto->arg_type_begin(), + NewProto->getNumArgs()), + EPI); New->setType(NewType); // If exceptions are disabled, suppress the warning about missing @@ -282,8 +296,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { SourceLocation FixItLoc; if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); - if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL)) - FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd()); + if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>()) + FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd()); } if (FixItLoc.isInvalid()) @@ -442,7 +456,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, // As a special compatibility feature, under C++0x we accept no spec and // throw(std::bad_alloc) as equivalent for operator new and operator new[]. // This is because the implicit declaration changed, but old code would break. - if (getLangOpts().CPlusPlus0x && IsOperatorNew) { + if (getLangOpts().CPlusPlus11 && IsOperatorNew) { const FunctionProtoType *WithExceptions = 0; if (OldEST == EST_None && NewEST == EST_Dynamic) WithExceptions = New; @@ -773,7 +787,7 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - if (getLangOpts().CPlusPlus0x && isa<CXXDestructorDecl>(New)) { + if (getLangOpts().CPlusPlus11 && isa<CXXDestructorDecl>(New)) { // Don't check uninstantiated template destructors at all. We can only // synthesize correct specs after the template is instantiated. if (New->getParent()->isDependentType()) |