diff options
author | dim <dim@FreeBSD.org> | 2011-06-12 18:01:31 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-06-12 18:01:31 +0000 |
commit | d4c7939beafe09c033866ebd290e274af0cc826d (patch) | |
tree | a9b264321873e7d25e69b8671c9f705ebc6d30ee /contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp | |
parent | b164882ef981a8ed5c085469231831e221fa1323 (diff) | |
parent | ece02cd5829cea836e9365b0845a8ef042d17b0a (diff) | |
download | FreeBSD-src-d4c7939beafe09c033866ebd290e274af0cc826d.zip FreeBSD-src-d4c7939beafe09c033866ebd290e274af0cc826d.tar.gz |
Upgrade our copy of llvm/clang to r132879, from upstream's trunk.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index 867d78f..ae154aa 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" #include "llvm/ADT/BitVector.h" @@ -126,18 +127,45 @@ static std::pair<unsigned,unsigned> InDiag = diag::note_protected_by_cleanup; OutDiag = diag::note_exits_cleanup; } else if (isCPlusPlus) { - // FIXME: In C++0x, we have to check more conditions than "did we - // just give it an initializer?". See 6.7p3. - if (VD->hasLocalStorage() && VD->hasInit()) - InDiag = diag::note_protected_by_variable_init; - - CanQualType T = VD->getType()->getCanonicalTypeUnqualified(); + if (!VD->hasLocalStorage()) + return std::make_pair(InDiag, OutDiag); + + ASTContext &Context = D->getASTContext(); + QualType T = Context.getBaseElementType(VD->getType()); if (!T->isDependentType()) { - while (CanQual<ArrayType> AT = T->getAs<ArrayType>()) - T = AT->getElementType(); - if (CanQual<RecordType> RT = T->getAs<RecordType>()) - if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor()) - OutDiag = diag::note_exits_dtor; + // C++0x [stmt.dcl]p3: + // A program that jumps from a point where a variable with automatic + // storage duration is not in scope to a point where it is in scope + // is ill-formed unless the variable has scalar type, class type with + // a trivial default constructor and a trivial destructor, a + // cv-qualified version of one of these types, or an array of one of + // the preceding types and is declared without an initializer (8.5). + // Check whether this is a C++ class. + CXXRecordDecl *Record = T->getAsCXXRecordDecl(); + + if (const Expr *Init = VD->getInit()) { + bool CallsTrivialConstructor = false; + if (Record) { + // FIXME: With generalized initializer lists, this may + // classify "X x{};" as having no initializer. + if (const CXXConstructExpr *Construct + = dyn_cast<CXXConstructExpr>(Init)) + if (const CXXConstructorDecl *Constructor + = Construct->getConstructor()) + if ((Context.getLangOptions().CPlusPlus0x + ? Record->hasTrivialDefaultConstructor() + : Record->isPOD()) && + Constructor->isDefaultConstructor()) + CallsTrivialConstructor = true; + } + + if (!CallsTrivialConstructor) + InDiag = diag::note_protected_by_variable_init; + } + + // Note whether we have a class with a non-trivial destructor. + if (Record && !Record->hasTrivialDestructor()) + OutDiag = diag::note_exits_dtor; } } |