diff options
| author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2009-06-17 22:50:06 +0000 | 
|---|---|---|
| committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2009-06-17 22:50:06 +0000 | 
| commit | 3df1978270c98b653879fcad35b6848f565e820c (patch) | |
| tree | 1bd964b7e90f5104d1cb8c8d5a6c4bf5657c5439 /clang | |
| parent | c4b766bc65927dd1b09c1014287aa5e0325dcb1c (diff) | |
| download | bcm5719-llvm-3df1978270c98b653879fcad35b6848f565e820c.tar.gz bcm5719-llvm-3df1978270c98b653879fcad35b6848f565e820c.zip  | |
Implement correct name lookup inside an initializer of a C++ class static data member.
Fixes "test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp" test case.
llvm-svn: 73652
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Parse/Action.h | 13 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 11 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 55 | ||||
| -rw-r--r-- | clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp | 1 | 
5 files changed, 86 insertions, 1 deletions
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index f1207e4f0f7..ba480c5b7c4 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -248,6 +248,19 @@ public:    virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {    } +  /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an +  /// initializer for the declaration 'Dcl'. +  /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a +  /// static data member of class X, names should be looked up in the scope of +  /// class X. +  virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { +  } + +  /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an +  /// initializer for the declaration 'Dcl'. +  virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { +  } +    /// ActOnDeclarator - This callback is invoked when a declarator is parsed and    /// 'Init' specifies the initializer if any.  This is for things like:    /// "int X = 4" or "typedef int foo". diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 9073c6dbd19..efabf3a7c6d 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -402,7 +402,14 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) {        SourceLocation DelLoc = ConsumeToken();        Actions.SetDeclDeleted(ThisDecl, DelLoc);      } else { +      if (getLang().CPlusPlus) +        Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl); +        OwningExprResult Init(ParseInitializer()); + +      if (getLang().CPlusPlus) +        Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl); +        if (Init.isInvalid()) {          SkipUntil(tok::semi, true, true);          return DeclPtrTy(); diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index bbfab88a3fd..579fe37feb5 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1721,6 +1721,17 @@ public:    /// defining scope.    virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS); +  /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an +  /// initializer for the declaration 'Dcl'. +  /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a +  /// static data member of class X, names should be looked up in the scope of +  /// class X. +  virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl); + +  /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an +  /// initializer for the declaration 'Dcl'. +  virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl); +    // ParseObjCStringLiteral - Parse Objective-C string literals.    virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,                                               ExprTy **Strings, diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index dcf11c54acf..bb1f50f104b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2828,3 +2828,58 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,    return false;  } + +/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an +/// initializer for the declaration 'Dcl'. +/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a +/// static data member of class X, names should be looked up in the scope of +/// class X. +void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { +  Decl *D = Dcl.getAs<Decl>(); +  // If there is no declaration, there was an error parsing it. +  if (D == 0) +    return; + +  // Check whether it is a declaration with a nested name specifier like +  // int foo::bar; +  if (!D->isOutOfLine()) +    return; +   +  // C++ [basic.lookup.unqual]p13 +  // +  // A name used in the definition of a static data member of class X +  // (after the qualified-id of the static member) is looked up as if the name +  // was used in a member function of X. +   +  // Change current context into the context of the initializing declaration. +   +  assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?"); +  PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity()); +  CurContext = D->getDeclContext(); +  assert(CurContext && "No context?"); +  S->setEntity(CurContext); +} + +/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an +/// initializer for the declaration 'Dcl'. +void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { +  Decl *D = Dcl.getAs<Decl>(); +  // If there is no declaration, there was an error parsing it. +  if (D == 0) +    return; + +  // Check whether it is a declaration with a nested name specifier like +  // int foo::bar; +  if (!D->isOutOfLine()) +    return; + +  assert(S->getEntity() == D->getDeclContext() && "Context imbalance!"); +  S->setEntity(PreDeclaratorDC); +  PreDeclaratorDC = 0; + +  // Reset CurContext to the nearest enclosing context. +  while (!S->getEntity() && S->getParent()) +    S = S->getParent(); +  CurContext = static_cast<DeclContext*>(S->getEntity()); +  assert(CurContext && "No context?"); +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp index 037d590f4eb..afd66236057 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp @@ -1,5 +1,4 @@  // RUN: clang-cc -fsyntax-only -verify %s -// XFAIL  struct S {    static const int f0 = 0;  | 

