diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Type.cpp | 41 | ||||
-rw-r--r-- | lib/Sema/SemaExprMember.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 18 |
3 files changed, 52 insertions, 12 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index ddeeacd551..3c4845d85a 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -897,37 +897,56 @@ bool Type::isConstantSizeType() const { /// isIncompleteType - Return true if this is an incomplete type (C99 6.2.5p1) /// - a type that can describe objects, but which lacks information needed to /// determine its size. -bool Type::isIncompleteType() const { +bool Type::isIncompleteType(NamedDecl **Def) const { + if (Def) + *Def = 0; + switch (CanonicalType->getTypeClass()) { default: return false; case Builtin: // Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never // be completed. return isVoidType(); - case Enum: + case Enum: { + EnumDecl *EnumD = cast<EnumType>(CanonicalType)->getDecl(); + if (Def) + *Def = EnumD; + // An enumeration with fixed underlying type is complete (C++0x 7.2p3). - if (cast<EnumType>(CanonicalType)->getDecl()->isFixed()) - return false; - // Fall through. - case Record: + if (EnumD->isFixed()) + return false; + + return !EnumD->isCompleteDefinition(); + } + case Record: { // A tagged type (struct/union/enum/class) is incomplete if the decl is a // forward declaration, but not a full definition (C99 6.2.5p22). - return !cast<TagType>(CanonicalType)->getDecl()->isCompleteDefinition(); + RecordDecl *Rec = cast<RecordType>(CanonicalType)->getDecl(); + if (Def) + *Def = Rec; + return !Rec->isCompleteDefinition(); + } case ConstantArray: // An array is incomplete if its element type is incomplete // (C++ [dcl.array]p1). // We don't handle variable arrays (they're not allowed in C++) or // dependent-sized arrays (dependent types are never treated as incomplete). - return cast<ArrayType>(CanonicalType)->getElementType()->isIncompleteType(); + return cast<ArrayType>(CanonicalType)->getElementType() + ->isIncompleteType(Def); case IncompleteArray: // An array of unknown size is an incomplete type (C99 6.2.5p22). return true; case ObjCObject: return cast<ObjCObjectType>(CanonicalType)->getBaseType() - ->isIncompleteType(); - case ObjCInterface: + ->isIncompleteType(Def); + case ObjCInterface: { // ObjC interfaces are incomplete if they are @class, not @interface. - return !cast<ObjCInterfaceType>(CanonicalType)->getDecl()->hasDefinition(); + ObjCInterfaceDecl *Interface + = cast<ObjCInterfaceType>(CanonicalType)->getDecl(); + if (Def) + *Def = Interface; + return !Interface->hasDefinition(); + } } } diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 65e444915c..3e7f8314d5 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -1084,6 +1084,11 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, goto fail; } + if (RequireCompleteType(OpLoc, BaseType, + PDiag(diag::err_typecheck_incomplete_tag) + << BaseExpr.get()->getSourceRange())) + return ExprError(); + ObjCInterfaceDecl *ClassDeclared; ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 3cececb8c4..f4b82fc1cb 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -27,6 +27,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Lookup.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -4059,8 +4060,23 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, // "Can't ask whether a dependent type is complete"); // If we have a complete type, we're done. - if (!T->isIncompleteType()) + NamedDecl *Def = 0; + if (!T->isIncompleteType(&Def)) { + // If we know about the definition but it is not visible, complain. + if (diag != 0 && Def && !LookupResult::isVisible(Def)) { + // Suppress this error outside of a SFINAE context if we've already + // emitted the error once for this type. There's no usefulness in + // repeating the diagnostic. + // FIXME: Add a Fix-It that imports the corresponding module or includes + // the header. + if (isSFINAEContext() || HiddenDefinitions.insert(Def)) { + Diag(Loc, diag::err_module_private_definition) << T; + Diag(Def->getLocation(), diag::note_previous_definition); + } + } + return false; + } const TagType *Tag = T->getAs<TagType>(); const ObjCInterfaceType *IFace = 0; |