diff options
| author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-11-07 22:02:30 +0000 | 
|---|---|---|
| committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2008-11-07 22:02:30 +0000 | 
| commit | e442635c37e56c92ba66f74bf73192751576c4e8 (patch) | |
| tree | b8d81feffff20b386b443d5f87d367e72a87aba8 /clang | |
| parent | cc0d2cfa014b3b53c605af443eef670b6ee596f3 (diff) | |
| download | bcm5719-llvm-e442635c37e56c92ba66f74bf73192751576c4e8.tar.gz bcm5719-llvm-e442635c37e56c92ba66f74bf73192751576c4e8.zip  | |
Changes in preparation for nested-name-specifiers.
-When parsing declarators, don't depend on "CurScope->isCXXClassScope() == true" for constructors/destructors
-For C++ member declarations, don't depend on "Declarator.getContext() == Declarator::MemberContext"
llvm-svn: 58866
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/DeclBase.h | 4 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticKinds.def | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 39 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 36 | ||||
| -rw-r--r-- | clang/test/SemaCXX/destructor.cpp | 3 | 
5 files changed, 53 insertions, 31 deletions
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index c44515eaa46..7670798d131 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -310,6 +310,10 @@ public:      }    } +  bool isCXXRecord() const { +    return DeclKind == Decl::CXXRecord; +  } +    const ScopedDecl *getDeclChain() const { return DeclChain; }    ScopedDecl *getDeclChain() { return DeclChain; }    void setDeclChain(ScopedDecl *D) { DeclChain = D; } diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index b3b6e81f9f1..726a6bd9eac 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -691,6 +691,8 @@ DIAG(err_constructor_byvalue_arg, ERROR,       "copy constructor must pass its first argument by reference")  // C++ destructors +DIAG(err_destructor_not_member, ERROR, +     "destructor must be a non-static member function")  DIAG(err_destructor_cannot_be, ERROR,       "destructor cannot be declared '%0'")  DIAG(err_invalid_qualified_destructor, ERROR, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 58cc9e2c6b3..2b18be02a3d 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1355,6 +1355,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, bool PtrOperator) {  ///         conversion-function-id  [TODO]  ///          '~' class-name           ///         template-id             [TODO] +///  void Parser::ParseDirectDeclarator(Declarator &D) {    // Parse the first direct-declarator seen.    if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { @@ -1362,31 +1363,35 @@ void Parser::ParseDirectDeclarator(Declarator &D) {      // Determine whether this identifier is a C++ constructor name or      // a normal identifier.      if (getLang().CPlusPlus &&  -        CurScope->isCXXClassScope() &&          Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))        D.SetConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope),                         Tok.getIdentifierInfo(), Tok.getLocation());      else        D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());      ConsumeToken(); -  } else if (getLang().CPlusPlus && Tok.is(tok::tilde) &&  -             CurScope->isCXXClassScope() && D.mayHaveIdentifier()) { +  } else if (getLang().CPlusPlus && +             Tok.is(tok::tilde) && D.mayHaveIdentifier()) {      // This should be a C++ destructor.      SourceLocation TildeLoc = ConsumeToken(); - -    // Use the next identifier and "~" to form a name for the -    // destructor. This is useful both for diagnostics and for -    // correctness of the parser, since we use presence/absence of the -    // identifier to determine what we parsed. -    // FIXME: We could end up with a template-id here, once we parse -    // templates, and will have to do something different to form the -    // name of the destructor. -    assert(Tok.is(tok::identifier) && "Expected identifier"); -    IdentifierInfo *II = Tok.getIdentifierInfo(); -    II = &PP.getIdentifierTable().get(std::string("~") + II->getName()); - -    if (TypeTy *Type = ParseClassName()) -      D.SetDestructor(Type, II, TildeLoc); +    if (Tok.is(tok::identifier)) { +      // Use the next identifier and "~" to form a name for the +      // destructor. This is useful both for diagnostics and for +      // correctness of the parser, since we use presence/absence of the +      // identifier to determine what we parsed. +      // FIXME: We could end up with a template-id here, once we parse +      // templates, and will have to do something different to form the +      // name of the destructor. +      IdentifierInfo *II = Tok.getIdentifierInfo(); +      II = &PP.getIdentifierTable().get(std::string("~") + II->getName()); + +      if (TypeTy *Type = ParseClassName()) +        D.SetDestructor(Type, II, TildeLoc); +      else +        D.SetIdentifier(0, TildeLoc); +    } else { +      Diag(Tok, diag::err_expected_class_name); +      D.SetIdentifier(0, TildeLoc); +    }    } else if (Tok.is(tok::kw_operator)) {      SourceLocation OperatorLoc = Tok.getLocation(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 12a4b08e919..18d77c4a18c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -811,7 +811,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {      FunctionDecl *NewFD;      if (D.getKind() == Declarator::DK_Constructor) {        // This is a C++ constructor declaration. -      assert(D.getContext() == Declarator::MemberContext && +      assert(CurContext->isCXXRecord() &&               "Constructors can only be declared in a member context");        bool isInvalidDecl = CheckConstructorDeclarator(D, R, SC); @@ -827,21 +827,29 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {          NewFD->setInvalidDecl();      } else if (D.getKind() == Declarator::DK_Destructor) {        // This is a C++ destructor declaration. -      assert(D.getContext() == Declarator::MemberContext && -             "Destructor can only be declared in a member context"); +      if (CurContext->isCXXRecord()) { +        bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC); -      bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC); - -      NewFD = CXXDestructorDecl::Create(Context, -                                        cast<CXXRecordDecl>(CurContext), -                                        D.getIdentifierLoc(), II, R,  -                                        isInline, -                                        /*isImplicitlyDeclared=*/false); +        NewFD = CXXDestructorDecl::Create(Context, +                                          cast<CXXRecordDecl>(CurContext), +                                          D.getIdentifierLoc(), II, R,  +                                          isInline, +                                          /*isImplicitlyDeclared=*/false); -      if (isInvalidDecl) +        if (isInvalidDecl) +          NewFD->setInvalidDecl(); +      } else { +        Diag(D.getIdentifierLoc(), diag::err_destructor_not_member); +        // Create a FunctionDecl to satisfy the function definition parsing +        // code path. +        NewFD = FunctionDecl::Create(Context, CurContext, D.getIdentifierLoc(), +                                     II, R, SC, isInline, LastDeclarator, +                                     // FIXME: Move to DeclGroup... +                                   D.getDeclSpec().getSourceRange().getBegin());          NewFD->setInvalidDecl(); +      }      } else if (D.getKind() == Declarator::DK_Conversion) { -      if (D.getContext() != Declarator::MemberContext) { +      if (!CurContext->isCXXRecord()) {          Diag(D.getIdentifierLoc(),               diag::err_conv_function_not_member);          return 0; @@ -856,7 +864,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {          if (isInvalidDecl)            NewFD->setInvalidDecl();        } -    } else if (D.getContext() == Declarator::MemberContext) { +    } else if (CurContext->isCXXRecord()) {        // This is a C++ method declaration.        NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(CurContext),                                      D.getIdentifierLoc(), II, R, @@ -1037,7 +1045,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {      case DeclSpec::SCS_register:       SC = VarDecl::Register; break;      case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;      }     -    if (D.getContext() == Declarator::MemberContext) { +    if (CurContext->isCXXRecord()) {        assert(SC == VarDecl::Static && "Invalid storage class for member!");        // This is a static data member for a C++ class.        NewVD = CXXClassVarDecl::Create(Context, cast<CXXRecordDecl>(CurContext), diff --git a/clang/test/SemaCXX/destructor.cpp b/clang/test/SemaCXX/destructor.cpp index 1eec0d5f007..cb5bd23a9eb 100644 --- a/clang/test/SemaCXX/destructor.cpp +++ b/clang/test/SemaCXX/destructor.cpp @@ -35,3 +35,6 @@ struct F {    ~F(); // expected-error{{destructor cannot be redeclared}}  }; +~; // expected-error {{expected class name}} +~undef(); // expected-error {{expected class name}} +~F(){} // expected-error {{destructor must be a non-static member function}}  | 

