diff options
| -rw-r--r-- | clang/include/clang/AST/ASTContext.h | 8 | ||||
| -rw-r--r-- | clang/include/clang/AST/Decl.h | 21 | ||||
| -rw-r--r-- | clang/include/clang/AST/Type.h | 17 | ||||
| -rw-r--r-- | clang/include/clang/Basic/SourceLocation.h | 21 | ||||
| -rw-r--r-- | clang/include/clang/Parse/Action.h | 2 | ||||
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 28 | ||||
| -rw-r--r-- | clang/lib/AST/DeclBase.cpp | 36 | ||||
| -rw-r--r-- | clang/lib/AST/TypeSerialization.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 70 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 1 | ||||
| -rw-r--r-- | clang/test/Sema/enum.c | 1 | ||||
| -rw-r--r-- | clang/test/SemaCXX/qualified-id-lookup.cpp | 18 | 
14 files changed, 125 insertions, 108 deletions
| diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ec48971aebf..7707b1d2158 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -543,14 +543,6 @@ private:    void InitBuiltinTypes();    void InitBuiltinType(QualType &R, BuiltinType::Kind K); -  /// setTagDefinition - Used by RecordDecl::completeDefinition and -  /// EnumDecl::completeDefinition to inform  -  /// about which RecordDecl/EnumDecl serves as the definition of a particular -  /// struct/union/class/enum. -  void setTagDefinition(TagDecl* R); -  friend class EnumDecl; -  friend class RecordDecl; -    // Return the ObjC type encoding for a given type.    void getObjCEncodingForTypeImpl(QualType t, std::string &S,                                     bool ExpandPointedToStructures, diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index f8e50925360..c0325bdafbb 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -887,6 +887,9 @@ class TypeDecl : public ScopedDecl {    /// ASTContext::getTagDeclType, and ASTContext::getTemplateTypeParmType.    Type *TypeForDecl;    friend class ASTContext; +  friend class DeclContext; +  friend class TagDecl; +  protected:    TypeDecl(Kind DK, DeclContext *DC, SourceLocation L,             IdentifierInfo *Id, ScopedDecl *PrevDecl) @@ -965,6 +968,16 @@ public:      return IsDefinition;    } +  /// @brief Starts the definition of this tag declaration. +  ///  +  /// This method should be invoked at the beginning of the definition +  /// of this tag declaration. It will set the tag type into a state +  /// where it is in the process of being defined. +  void startDefinition(); + +  /// @brief Completes the definition of this tag declaration. +  void completeDefinition(); +    /// getDefinition - Returns the TagDecl that actually defines this     ///  struct/union/class/enum.  When determining whether or not a    ///  struct/union/class/enum is completely defined, one should use this method @@ -998,6 +1011,14 @@ public:      return D->getKind() >= TagFirst && D->getKind() <= TagLast;    }    static bool classof(const TagDecl *D) { return true; } + +  static DeclContext *castToDeclContext(const TagDecl *D) { +    return static_cast<DeclContext *>(const_cast<TagDecl*>(D)); +  } +  static TagDecl *castFromDeclContext(const DeclContext *DC) { +    return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); +  } +  protected:    void setDefinition(bool V) { IsDefinition = V; }  }; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index afcd1edd80f..a74ac953244 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1194,19 +1194,30 @@ protected:  };  class TagType : public Type { -  TagDecl *decl; +  /// Stores the TagDecl associated with this type. The decl will +  /// point to the TagDecl that actually defines the entity (or is a +  /// definition in progress), if there is such a definition. The +  /// single-bit value will be non-zero when this tag is in the +  /// process of being defined. +  llvm::PointerIntPair<TagDecl *, 1> decl;    friend class ASTContext; +  friend class TagDecl;  protected:    // FIXME: We'll need the user to pass in information about whether    // this type is dependent or not, because we don't have enough    // information to compute it here.    TagType(TagDecl *D, QualType can)  -    : Type(Tagged, can, /*Dependent=*/false), decl(D) {} +    : Type(Tagged, can, /*Dependent=*/false), decl(D, 0) {}  public:    -  TagDecl *getDecl() const { return decl; } +  TagDecl *getDecl() const { return decl.getPointer(); } +  /// @brief Determines whether this type is in the process of being +  /// defined.  +  bool isBeingDefined() const { return decl.getInt(); } +  void setBeingDefined(bool Def) { decl.setInt(Def? 1 : 0); } +    virtual void getAsStringInternal(std::string &InnerString) const;    static bool classof(const Type *T) { return T->getTypeClass() == Tagged; } diff --git a/clang/include/clang/Basic/SourceLocation.h b/clang/include/clang/Basic/SourceLocation.h index da7ea25a546..ba359bddaec 100644 --- a/clang/include/clang/Basic/SourceLocation.h +++ b/clang/include/clang/Basic/SourceLocation.h @@ -253,17 +253,20 @@ public:    /// Prints information about this FullSourceLoc to stderr. Useful for    ///  debugging.    void dump() const; -}; -inline bool operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { -  return LHS.getRawEncoding() == RHS.getRawEncoding() && -         &LHS.getManager() == &RHS.getManager(); -} +  friend inline bool  +  operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { +    return LHS.getRawEncoding() == RHS.getRawEncoding() && +          LHS.SrcMgr == RHS.SrcMgr; +  } -inline bool operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { -  return !(LHS == RHS); -} -   +  friend inline bool  +  operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { +    return !(LHS == RHS); +  } + +}; +   }  // end namespace clang  #endif diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index d0891bb3504..f78f4f38d14 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -310,7 +310,7 @@ public:      TK_Declaration, // Fwd decl of a tag:   'struct foo;'      TK_Definition   // Definition of a tag: 'struct foo { int X; } Y;'    }; -  virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK, +  virtual DeclTy *ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,                             SourceLocation KWLoc, const CXXScopeSpec &SS,                             IdentifierInfo *Name, SourceLocation NameLoc,                             AttributeList *Attr, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 8e7410c47c7..7cb035b8680 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1076,11 +1076,6 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) {    return QualType(Decl->TypeForDecl, 0);  } -void ASTContext::setTagDefinition(TagDecl* D) { -  assert (D->isDefinition()); -  cast<TagType>(D->TypeForDecl)->decl = D;   -} -  /// getTypedefType - Return the unique reference to the type for the  /// specified typename decl.  QualType ASTContext::getTypedefType(TypedefDecl *Decl) { diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 0bc0043ccb8..8ae93110170 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -144,13 +144,8 @@ void EnumDecl::Destroy(ASTContext& C) {  void EnumDecl::completeDefinition(ASTContext &C, QualType NewType) {    assert(!isDefinition() && "Cannot redefine enums!"); -  setDefinition(true); -    IntegerType = NewType; - -  // Let ASTContext know that this is the defining EnumDecl for this -  // type. -  C.setTagDefinition(this); +  TagDecl::completeDefinition();  }  FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, @@ -311,6 +306,20 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {  // TagDecl Implementation  //===----------------------------------------------------------------------===// +void TagDecl::startDefinition() { +  cast<TagType>(TypeForDecl)->decl.setPointer(this); +  cast<TagType>(TypeForDecl)->decl.setInt(1); +} + +void TagDecl::completeDefinition() { +  assert((!TypeForDecl ||  +          cast<TagType>(TypeForDecl)->decl.getPointer() == this) && +         "Attempt to redefine a tag definition?"); +  IsDefinition = true; +  cast<TagType>(TypeForDecl)->decl.setPointer(this); +  cast<TagType>(TypeForDecl)->decl.setInt(0); +} +  TagDecl* TagDecl::getDefinition(ASTContext& C) const {    QualType T = C.getTypeDeclType(const_cast<TagDecl*>(this));    TagDecl* D = cast<TagDecl>(cast<TagType>(T)->getDecl());   @@ -351,12 +360,7 @@ void RecordDecl::Destroy(ASTContext& C) {  /// complete.  void RecordDecl::completeDefinition(ASTContext& C) {    assert(!isDefinition() && "Cannot redefine record!"); - -  setDefinition(true); -   -  // Let ASTContext know that this is the defining RecordDecl for this -  // type. -  C.setTagDefinition(this); +  TagDecl::completeDefinition();  }  //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 860a65a1e3e..28656873ab0 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -442,37 +442,15 @@ DeclContext *DeclContext::getPrimaryContext() {      return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();    case Decl::Enum: -#if 0 -    // FIXME: See the comment for CXXRecord, below. -    // The declaration associated with the enumeration type is our -    // primary context. -    return Context.getTypeDeclType(static_cast<EnumDecl*>(this)) -             ->getAsEnumType()->getDecl(); -#else -    return this; -#endif -    case Decl::Record: -  case Decl::CXXRecord: { -    // The declaration associated with the type is be our primary -    // context.  -#if 0 -    // FIXME: This is what we expect to do. However, it doesn't work -    // because ASTContext::setTagDefinition changes the result of -    // Context.getTypeDeclType, meaning that our "primary" declaration -    // of a RecordDecl/CXXRecordDecl will change, and we won't be able -    // to find any values inserted into the earlier "primary" -    // declaration. We need better tracking of redeclarations and -    // definitions. -    QualType Type = Context.getTypeDeclType(static_cast<RecordDecl*>(this)); -    return Type->getAsRecordType()->getDecl(); -#else -    // FIXME: This hack will work for now, because the declaration we -    // create when we're defining the record is the one we'll use as -    // the definition later. +  case Decl::CXXRecord: +    // If this is a tag type that has a definition or is currently +    // being defined, that definition is our primary context. +    if (TagType *TagT = cast_or_null<TagType>(cast<TagDecl>(this)->TypeForDecl)) +      if (TagT->isBeingDefined() ||  +          (TagT->getDecl() && TagT->getDecl()->isDefinition())) +        return TagT->getDecl();      return this; -#endif -  }    case Decl::ObjCMethod:      return this; diff --git a/clang/lib/AST/TypeSerialization.cpp b/clang/lib/AST/TypeSerialization.cpp index 42569da400a..4f3eeca28c6 100644 --- a/clang/lib/AST/TypeSerialization.cpp +++ b/clang/lib/AST/TypeSerialization.cpp @@ -258,7 +258,8 @@ Type* TagType::CreateImpl(ASTContext& Context, Deserializer& D) {    Types.push_back(T);    // Deserialize the decl. -  T->decl = cast<TagDecl>(D.ReadOwnedPtr<Decl>(Context)); +  T->decl.setPointer(cast<TagDecl>(D.ReadOwnedPtr<Decl>(Context))); +  T->decl.setInt(0);    return T;  } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index be9da6bd80f..72de7107c80 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -319,7 +319,7 @@ public:    virtual DeclTy *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,                                                 RecordDecl *Record); -  virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK, +  virtual DeclTy *ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,                             SourceLocation KWLoc, const CXXScopeSpec &SS,                             IdentifierInfo *Name, SourceLocation NameLoc,                             AttributeList *Attr, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cfd33f6123d..73465262659 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2813,9 +2813,9 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,  /// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'.  In the  /// former case, Name will be non-null.  In the later case, Name will be null. -/// TagType indicates what kind of tag this is. TK indicates whether this is a +/// TagSpec indicates what kind of tag this is. TK indicates whether this is a  /// reference/declaration/definition of a tag. -Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK, +Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,                               SourceLocation KWLoc, const CXXScopeSpec &SS,                               IdentifierInfo *Name, SourceLocation NameLoc,                               AttributeList *Attr, @@ -2825,7 +2825,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,           "Nameless record must be a definition!");    TagDecl::TagKind Kind; -  switch (TagType) { +  switch (TagSpec) {    default: assert(0 && "Unknown tag type!");    case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;    case DeclSpec::TST_union:  Kind = TagDecl::TK_union; break; @@ -2838,6 +2838,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,    DeclContext *LexicalContext = CurContext;    ScopedDecl *PrevDecl = 0; +  bool Invalid = false; +    if (Name && SS.isNotEmpty()) {      // We have a nested-name tag ('struct foo::bar'). @@ -2898,6 +2900,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,            // Recover by making this an anonymous redefinition.            Name = 0;            PrevDecl = 0; +          Invalid = true;          } else {            // If this is a use, just return the declaration we found. @@ -2913,15 +2916,29 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,              if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) {                Diag(NameLoc, diag::err_redefinition) << Name;                Diag(Def->getLocation(), diag::note_previous_definition); -              // If this is a redefinition, recover by making this struct be -              // anonymous, which will make any later references get the previous -              // definition. +              // If this is a redefinition, recover by making this +              // struct be anonymous, which will make any later +              // references get the previous definition.                Name = 0;                PrevDecl = 0; +              Invalid = true; +            } else { +              // If the type is currently being defined, complain +              // about a nested redefinition. +              TagType *Tag = cast<TagType>(Context.getTagDeclType(PrevTagDecl)); +              if (Tag->isBeingDefined()) { +                Diag(NameLoc, diag::err_nested_redefinition) << Name; +                Diag(PrevTagDecl->getLocation(),  +                     diag::note_previous_definition); +                Name = 0; +                PrevDecl = 0; +                Invalid = true; +              }              } +              // Okay, this is definition of a previously declared or referenced              // tag PrevDecl. We're going to create a new Decl for it. -          }  +          }          }          // If we get here we have (another) forward declaration or we          // have a definition.  Just create a new decl.         @@ -2944,6 +2961,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,          Diag(PrevDecl->getLocation(), diag::note_previous_definition);          Name = 0;          PrevDecl = 0; +        Invalid = true;        } else {          // The existing declaration isn't relevant to us; we're in a          // new scope, so clear out the previous declaration. @@ -3034,16 +3052,23 @@ CreateNewDecl:        New->addAttr(new PackedAttr(Alignment * 8));    } +  if (Invalid) +    New->setInvalidDecl(); +    if (Attr)      ProcessDeclAttributeList(New, Attr); -  // If we're declaring or defining  +  // If we're declaring or defining a tag in function prototype scope +  // in C, note that this type can only be used within the function.    if (Name && S->isFunctionPrototypeScope() && !getLangOptions().CPlusPlus)      Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);    // Set the lexical context. If the tag has a C++ scope specifier, the    // lexical context will be different from the semantic context.    New->setLexicalDeclContext(LexicalContext); + +  if (TK == TK_Definition) +    New->startDefinition();    // If this has an identifier, add it to the scope stack.    if (Name) { @@ -3332,22 +3357,6 @@ void Sema::ActOnFields(Scope* S,    assert(EnclosingDecl && "missing record or interface decl");    RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); -  if (Record) { -    QualType RecordType = Context.getTypeDeclType(Record); -    if (RecordType->getAsRecordType()->getDecl()->isDefinition()) { -      RecordDecl *Def = RecordType->getAsRecordType()->getDecl(); -      // Diagnose code like: -      //     struct S { struct S {} X; }; -      // We discover this when we complete the outer S.  Reject and ignore the -      // outer S. -      Diag(Def->getLocation(), diag::err_nested_redefinition) -        << Def->getDeclName(); -      Diag(RecLoc, diag::note_previous_definition); -      Record->setInvalidDecl(); -      return; -    } -  } -      // Verify that all the fields are okay.    unsigned NumNamedMembers = 0;    llvm::SmallVector<FieldDecl*, 32> RecFields; @@ -3564,19 +3573,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,    EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));    QualType EnumType = Context.getTypeDeclType(Enum); -  if (EnumType->getAsEnumType()->getDecl()->isDefinition()) { -    EnumDecl *Def = EnumType->getAsEnumType()->getDecl(); -    // Diagnose code like: -    //   enum e0 { -    //     E0 = sizeof(enum e0 { E1 }) -    //   }; -    Diag(Def->getLocation(), diag::err_nested_redefinition) -      << Enum->getDeclName(); -    Diag(Enum->getLocation(), diag::note_previous_definition); -    Enum->setInvalidDecl(); -    return; -  } -    // TODO: If the result value doesn't fit in an int, it must be a long or long    // long value.  ISO C does not support this, but GCC does as an extension,    // emit a warning. diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index a16c28b9dce..561ed205e89 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -625,6 +625,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,        ++Found;      Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); +      return true;    }  diff --git a/clang/test/Sema/enum.c b/clang/test/Sema/enum.c index 4c24b580d8f..b42036dc02e 100644 --- a/clang/test/Sema/enum.c +++ b/clang/test/Sema/enum.c @@ -1,5 +1,4 @@  // RUN: clang %s -fsyntax-only -verify -pedantic -  enum e {A,           B = 42LL << 32,        // expected-warning {{ISO C restricts enumerator values to range of 'int'}}        C = -4, D = 12456 }; diff --git a/clang/test/SemaCXX/qualified-id-lookup.cpp b/clang/test/SemaCXX/qualified-id-lookup.cpp index 34c06140d89..cf86971f350 100644 --- a/clang/test/SemaCXX/qualified-id-lookup.cpp +++ b/clang/test/SemaCXX/qualified-id-lookup.cpp @@ -44,7 +44,10 @@ namespace N {    }  } -void N::f1::foo(int) { } +void N::f1::foo(int i) {  +  f1::member = i;  +  f1::type &ir = i; +}  namespace N {    float& f1(int x) { @@ -93,4 +96,17 @@ void test_a() {    a::a::a::i = 4;  } +struct Undef { +  typedef int type; + +  Undef::type member; + +  static int size = sizeof(Undef); // expected-error{{invalid application of 'sizeof' to an incomplete type 'struct Undef'}} + +  int f(); +}; + +int Undef::f() { +  return sizeof(Undef); +} | 

