[cfe-commits] r132191 - in /cfe/trunk: lib/Sema/JumpDiagnostics.cpp test/CXX/stmt.stmt/stmt.dcl/p3.cpp
Douglas Gregor
dgregor at apple.com
Fri May 27 09:05:29 PDT 2011
Author: dgregor
Date: Fri May 27 11:05:29 2011
New Revision: 132191
URL: http://llvm.org/viewvc/llvm-project?rev=132191&view=rev
Log:
Update the jump-scope checker for local variables with initializers,
so that it looks at the initializer of a local variable of class type
(or array thereof) to determine whether it's just an implicit
invocation of the trivial default constructor. Fixes PR10034.
Added:
cfe/trunk/test/CXX/stmt.stmt/stmt.dcl/p3.cpp (with props)
Modified:
cfe/trunk/lib/Sema/JumpDiagnostics.cpp
Modified: cfe/trunk/lib/Sema/JumpDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/JumpDiagnostics.cpp?rev=132191&r1=132190&r2=132191&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/JumpDiagnostics.cpp (original)
+++ cfe/trunk/lib/Sema/JumpDiagnostics.cpp Fri May 27 11:05:29 2011
@@ -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,48 @@
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())
+ // 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).
+ if (VD->hasLocalStorage() && Context.getLangOptions().CPlusPlus) {
+ // 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 (Constructor->isDefaultConstructor() &&
+ ((Context.getLangOptions().CPlusPlus0x &&
+ Record->hasTrivialDefaultConstructor()) ||
+ (!Context.getLangOptions().CPlusPlus0x &&
+ Record->isPOD())))
+ 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;
+ }
}
}
Added: cfe/trunk/test/CXX/stmt.stmt/stmt.dcl/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/stmt.stmt/stmt.dcl/p3.cpp?rev=132191&view=auto
==============================================================================
--- cfe/trunk/test/CXX/stmt.stmt/stmt.dcl/p3.cpp (added)
+++ cfe/trunk/test/CXX/stmt.stmt/stmt.dcl/p3.cpp Fri May 27 11:05:29 2011
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// PR10034
+struct X {};
+
+void exx(X) {}
+
+int main(int argc, char **argv)
+{
+ if (argc > 3)
+ goto end;
+
+ X x;
+ X xs[16];
+ exx(x);
+
+ end:
+ if (argc > 1) {
+ for (int i = 0; i < argc; ++i)
+ {
+
+ }
+ }
+ return 0;
+}
Propchange: cfe/trunk/test/CXX/stmt.stmt/stmt.dcl/p3.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/CXX/stmt.stmt/stmt.dcl/p3.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/CXX/stmt.stmt/stmt.dcl/p3.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list