aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-01-19 19:26:10 +0000
committerDouglas Gregor <dgregor@apple.com>2009-01-19 19:26:10 +0000
commit4ec339f43c0cae2678334850c90926bea10999c7 (patch)
tree618cd12f3da4ef770bbd1d79573b85cb4c7eda1b /lib/Sema/SemaType.cpp
parentfec7c2a9d0d46f4e681d1fe0089ae590962f05f6 (diff)
Centralize error reporting of improper uses of incomplete types in the
new DiagnoseIncompleteType. It provides additional information about struct/class/union/enum types when possible, either by pointing to the forward declaration of that type or by pointing to the definition (if we're in the process of defining that type). Fixes <rdar://problem/6500531>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62521 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp68
1 files changed, 65 insertions, 3 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 8a459f4d3e..ecae79320d 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -352,9 +352,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
- if (T->isIncompleteType()) {
- Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_incomplete_type)
- << T;
+ if (DiagnoseIncompleteType(D.getIdentifierLoc(), T,
+ diag::err_illegal_decl_array_incomplete_type)) {
T = Context.IntTy;
D.setInvalidType(true);
} else if (T->isFunctionType()) {
@@ -690,4 +689,67 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) {
}
}
+/// @brief If the type T is incomplete and cannot be completed,
+/// produce a suitable diagnostic.
+///
+/// This routine checks whether the type @p T is complete in any
+/// context where a complete type is required. If @p T is a complete
+/// type, returns false. If @p T is incomplete, issues the diagnostic
+/// @p diag (giving it the type @p T) and returns true.
+///
+/// @param Loc The location in the source that the incomplete type
+/// diagnostic should refer to.
+///
+/// @param T The type that this routine is examining for completeness.
+///
+/// @param diag The diagnostic value (e.g.,
+/// @c diag::err_typecheck_decl_incomplete_type) that will be used
+/// for the error message if @p T is incomplete.
+///
+/// @param Range1 An optional range in the source code that will be a
+/// part of the "incomplete type" error message.
+///
+/// @param Range2 An optional range in the source code that will be a
+/// part of the "incomplete type" error message.
+///
+/// @param PrintType If non-NULL, the type that should be printed
+/// instead of @p T. This parameter should be used when the type that
+/// we're checking for incompleteness isn't the type that should be
+/// displayed to the user, e.g., when T is a type and PrintType is a
+/// pointer to T.
+///
+/// @returns @c true if @p T is incomplete and a diagnostic was emitted,
+/// @c false otherwise.
+///
+/// @todo When Clang gets proper support for C++ templates, this
+/// routine will also be able perform template instantiation when @p T
+/// is a class template specialization.
+bool Sema::DiagnoseIncompleteType(SourceLocation Loc, QualType T, unsigned diag,
+ SourceRange Range1, SourceRange Range2,
+ QualType PrintType) {
+ // If we have a complete type, we're done.
+ if (!T->isIncompleteType())
+ return false;
+
+ if (PrintType.isNull())
+ PrintType = T;
+
+ // We have an incomplete type. Produce a diagnostic.
+ Diag(Loc, diag) << PrintType << Range1 << Range2;
+ // If the type was a forward declaration of a class/struct/union
+ // type, produce
+ const TagType *Tag = 0;
+ if (const RecordType *Record = T->getAsRecordType())
+ Tag = Record;
+ else if (const EnumType *Enum = T->getAsEnumType())
+ Tag = Enum;
+
+ if (Tag && !Tag->getDecl()->isInvalidDecl())
+ Diag(Tag->getDecl()->getLocation(),
+ Tag->isBeingDefined() ? diag::note_type_being_defined
+ : diag::note_forward_declaration)
+ << QualType(Tag, 0);
+
+ return true;
+}