diff options
author | John McCall <rjmccall@apple.com> | 2010-03-31 02:13:20 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-03-31 02:13:20 +0000 |
commit | 7727acf243ee61c0757d86c95b69dbee56a3d898 (patch) | |
tree | 7d0e27420e5bf67084dfceef74710da60a4d0171 | |
parent | 32daa4223ccb2c0afe5fbe151c6eb1ab64816957 (diff) |
Fix PR6327: restore invariants when there's a parse error in an initializer.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99980 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 35 | ||||
-rw-r--r-- | test/Sema/init.c | 3 | ||||
-rw-r--r-- | test/SemaCXX/invalid-member-expr.cpp | 18 |
4 files changed, 56 insertions, 1 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 1909607e2d..72e7f17704 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -828,6 +828,7 @@ public: virtual void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init); void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit); void ActOnUninitializedDecl(DeclPtrTy dcl, bool TypeContainsUndeducedAuto); + virtual void ActOnInitializerError(DeclPtrTy Dcl); virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc); virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, DeclPtrTy *Group, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b60804a189..51514e77a2 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3797,6 +3797,41 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { return; } +/// ActOnInitializerError - Given that there was an error parsing an +/// initializer for the given declaration, try to return to some form +/// of sanity. +void Sema::ActOnInitializerError(DeclPtrTy dcl) { + // Our main concern here is re-establishing invariants like "a + // variable's type is either dependent or complete". + Decl *D = dcl.getAs<Decl>(); + if (!D || D->isInvalidDecl()) return; + + VarDecl *VD = dyn_cast<VarDecl>(D); + if (!VD) return; + + QualType Ty = VD->getType(); + if (Ty->isDependentType()) return; + + // Require a complete type. + if (RequireCompleteType(VD->getLocation(), + Context.getBaseElementType(Ty), + diag::err_typecheck_decl_incomplete_type)) { + VD->setInvalidDecl(); + return; + } + + // Require an abstract type. + if (RequireNonAbstractType(VD->getLocation(), Ty, + diag::err_abstract_type_in_decl, + AbstractVariableType)) { + VD->setInvalidDecl(); + return; + } + + // Don't bother complaining about constructors or destructors, + // though. +} + void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, bool TypeContainsUndeducedAuto) { Decl *RealDecl = dcl.getAs<Decl>(); diff --git a/test/Sema/init.c b/test/Sema/init.c index c2712480c6..b9867cf502 100644 --- a/test/Sema/init.c +++ b/test/Sema/init.c @@ -75,7 +75,8 @@ int sym_fw1a_scr[] = { }; // PR3001 -struct s1 s2 = { +struct s1 s2 = { // expected-error {{variable has incomplete type 'struct s1'}} \ + // expected-note {{forward declaration of 'struct s1'}} .a = sizeof(struct s3), // expected-error {{invalid application of 'sizeof'}} \ // expected-note{{forward declaration of 'struct s3'}} .b = bogus // expected-error {{use of undeclared identifier 'bogus'}} diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp index 7b17afbf81..7307a47f82 100644 --- a/test/SemaCXX/invalid-member-expr.cpp +++ b/test/SemaCXX/invalid-member-expr.cpp @@ -19,3 +19,21 @@ void test2() { x->operator; // expected-error{{missing type specifier after 'operator'}} x->operator typedef; // expected-error{{missing type specifier after 'operator'}} } + +// PR6327 +namespace test3 { + template <class A, class B> struct pair {}; + + void test0() { + pair<int, int> z = minmax({}); // expected-error {{expected expression}} + } + + struct string { + class iterator {}; + }; + + void test1() { + string s; + string::iterator i = s.foo(); // expected-error {{no member named 'foo'}} + } +} |