summaryrefslogtreecommitdiffstats
path: root/include/clang
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2017-07-01 00:06:47 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2017-07-01 00:06:47 +0000
commitf4f39fd907f26918104f7b899146bcb72030862d (patch)
tree25cc0b98f0df02ee730a75052fa6a6d5045b172a /include/clang
parent9a860738b816ad8756eb18113ff146c7f2899960 (diff)
[Modules] Implement ODR-like semantics for tag types in C/ObjC
Allow ODR for ObjC/C in the sense that we won't keep more that one definition around (merge them). However, ensure the decl pass the structural compatibility check in C11 6.2.7/1, for that, reuse the structural equivalence checks used by the ASTImporter. Few other considerations: - Create error diagnostics for tag types mismatches and thread them into the structural equivalence checks. - Note that by doing this we only support redefinition between types that are considered "compatible types" by C. This is mixed approach of the suggestions discussed in http://lists.llvm.org/pipermail/cfe-dev/2017-March/053257.html Differential Revision: https://reviews.llvm.org/D31778 rdar://problem/31909368 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@306918 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/ASTStructuralEquivalence.h6
-rw-r--r--include/clang/Basic/DiagnosticASTKinds.td11
-rw-r--r--include/clang/Sema/Sema.h32
3 files changed, 34 insertions, 15 deletions
diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h
index 770bb5763f..23674c65f3 100644
--- a/include/clang/AST/ASTStructuralEquivalence.h
+++ b/include/clang/AST/ASTStructuralEquivalence.h
@@ -62,9 +62,11 @@ struct StructuralEquivalenceContext {
StructuralEquivalenceContext(
ASTContext &FromCtx, ASTContext &ToCtx,
llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls,
- bool StrictTypeSpelling = false, bool Complain = true)
+ bool StrictTypeSpelling = false, bool Complain = true,
+ bool ErrorOnTagTypeMismatch = false)
: FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls),
- StrictTypeSpelling(StrictTypeSpelling), Complain(Complain),
+ StrictTypeSpelling(StrictTypeSpelling),
+ ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain),
LastDiagFromC2(false) {}
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID);
diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td
index 652d062785..b3cba2066e 100644
--- a/include/clang/Basic/DiagnosticASTKinds.td
+++ b/include/clang/Basic/DiagnosticASTKinds.td
@@ -200,12 +200,17 @@ def note_odr_defined_here : Note<"also defined here">;
def err_odr_function_type_inconsistent : Error<
"external function %0 declared with incompatible types in different "
"translation units (%1 vs. %2)">;
-def warn_odr_tag_type_inconsistent : Warning<
- "type %0 has incompatible definitions in different translation units">,
- InGroup<DiagGroup<"odr">>;
+def warn_odr_tag_type_inconsistent
+ : Warning<"type %0 has incompatible definitions in different translation "
+ "units">,
+ InGroup<DiagGroup<"odr">>;
+def err_odr_tag_type_inconsistent
+ : Error<"type %0 has incompatible definitions in different translation "
+ "units">;
def note_odr_tag_kind_here: Note<
"%0 is a %select{struct|interface|union|class|enum}1 here">;
def note_odr_field : Note<"field %0 has type %1 here">;
+def note_odr_field_name : Note<"field has name %0 here">;
def note_odr_missing_field : Note<"no corresponding field here">;
def note_odr_bit_field : Note<"bit-field %0 with type %1 and length %2 here">;
def note_odr_not_bit_field : Note<"field %0 is not a bit-field">;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 75ff5fdb37..95134d52f8 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1542,6 +1542,10 @@ public:
bool hasVisibleMergedDefinition(NamedDecl *Def);
+ /// Determine if \p D and \p Suggested have a structurally compatible
+ /// layout as described in C11 6.2.7/1.
+ bool hasStructuralCompatLayout(Decl *D, Decl *Suggested);
+
/// Determine if \p D has a visible definition. If not, suggest a declaration
/// that should be made visible to expose the definition.
bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
@@ -1629,9 +1633,13 @@ public:
//
struct SkipBodyInfo {
- SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
+ SkipBodyInfo()
+ : ShouldSkip(false), CheckSameAsPrevious(false), Previous(nullptr),
+ New(nullptr) {}
bool ShouldSkip;
+ bool CheckSameAsPrevious;
NamedDecl *Previous;
+ NamedDecl *New;
};
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
@@ -2145,13 +2153,11 @@ public:
};
Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr, AccessSpecifier AS,
- SourceLocation ModulePrivateLoc,
- MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl, bool &IsDependent,
- SourceLocation ScopedEnumKWLoc,
+ SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation NameLoc, AttributeList *Attr,
+ AccessSpecifier AS, SourceLocation ModulePrivateLoc,
+ MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl,
+ bool &IsDependent, SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
bool IsTypeSpecifier, bool IsTemplateParamOrArg,
SkipBodyInfo *SkipBody = nullptr);
@@ -2219,6 +2225,12 @@ public:
/// struct, or union).
void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
+ /// Perform ODR-like check for C/ObjC when merging tag types from modules.
+ /// Differently from C++, actually parse the body and reject / error out
+ /// in case of a structural mismatch.
+ bool ActOnDuplicateDefinition(DeclSpec &DS, Decl *Prev,
+ SkipBodyInfo &SkipBody);
+
typedef void *SkippedDefinitionContext;
/// \brief Invoked when we enter a tag definition that we're skipping.
@@ -2272,8 +2284,8 @@ public:
Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
SourceLocation IdLoc, IdentifierInfo *Id,
- AttributeList *Attrs,
- SourceLocation EqualLoc, Expr *Val);
+ AttributeList *Attrs, SourceLocation EqualLoc,
+ Expr *Val);
void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
Decl *EnumDecl,
ArrayRef<Decl *> Elements,