[clang] [Modules] Detect ODR mismatches for enums in non-C++ like in C++. (PR #90298)
vsapsai wrote: In C++ we reject mismatched types coming from different Clang modules. Haven't checked the behavior for C++20 modules as I'm not changing it. In C modules aren't a part of any standard as far as I know. But for Clang modules we reject most of the mismatched types coming from different modules. The current change extends the set of "most of the mismatched types" to include enums. https://github.com/llvm/llvm-project/pull/90298 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] Detect ODR mismatches for enums in non-C++ like in C++. (PR #90298)
https://github.com/vsapsai closed https://github.com/llvm/llvm-project/pull/90298 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] Detect ODR mismatches for enums in non-C++ like in C++. (PR #90298)
vsapsai wrote: @dwblaikie if you have no further comments, I'll merge this approved change some time soon (in a day or two). https://github.com/llvm/llvm-project/pull/90298 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] Detect ODR mismatches for enums in non-C++ like in C++. (PR #90298)
vsapsai wrote: > Not sure I'm following the response here - but I guess what I'm trying to > say, with more words, is that my understanding was that C doesn't have an > ODR, and you can have different definitions of a type, with the same name, in > C and that's OK. In different translation units you can still use different types with the same name. And you can use enum constant with the same name but different values. It is still OK from the compiler's perspective. > And it sounds like this change makes that not OK in some way? (either by > diagnosing/erroring on such divergent types, or assuming they won't diverge > and carrying on silently) The change is for Clang modules only. In the non-modular world including the same file twice (no header guards, no pragma once) would result in a type redefinition. But with modules it is more likely to find the same type definition in multiple modules. To make the compiler more practical we don't reject such situations. Though we detect when the types aren't identical and don't try to use them interchangeably. The change extends the existing behavior for structs/unions to enums. If you have use cases when different enums should be used interchangeably, I can see how to accommodate such use cases. https://github.com/llvm/llvm-project/pull/90298 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] Detect ODR mismatches for enums in non-C++ like in C++. (PR #90298)
vsapsai wrote: > C doesn't have an odr, does it? For non-C++ "ODR" has a meaning more like "ODR-inspired checks". But there is no language rule that would require enforcement and there is no impact on linkage (at least during deserialization). https://github.com/llvm/llvm-project/pull/90298 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] Detect ODR mismatches for enums in non-C++ like in C++. (PR #90298)
https://github.com/vsapsai created https://github.com/llvm/llvm-project/pull/90298 There is no reason for C and Objective-C to differ from C++ in this matter. rdar://85531830 >From 8dafc9af06eef1a4b3fba8b5cffeece62967a6fd Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai Date: Fri, 26 Apr 2024 16:33:26 -0700 Subject: [PATCH] [Modules] Detect ODR mismatches for enums in non-C++ like in C++. There is no reason for C and Objective-C to differ from C++ in this matter. rdar://85531830 --- clang/lib/Serialization/ASTReaderDecl.cpp | 7 +-- clang/test/Modules/odr_hash-enum.c| 75 +++ 2 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 clang/test/Modules/odr_hash-enum.c diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 744f11de88c2f8..6afbbfe20f26b7 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -805,9 +805,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { // If this is a definition subject to the ODR, and we already have a // definition, merge this one into it. - if (ED->isCompleteDefinition() && - Reader.getContext().getLangOpts().Modules && - Reader.getContext().getLangOpts().CPlusPlus) { + if (ED->isCompleteDefinition() && Reader.getContext().getLangOpts().Modules) { EnumDecl * = Reader.EnumDefinitions[ED->getCanonicalDecl()]; if (!OldDef) { // This is the first time we've seen an imported definition. Look for a @@ -3304,8 +3302,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader , return RD->getDefinition(); if (auto *ED = dyn_cast(DC)) -return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() - : nullptr; +return ED->getDefinition(); if (auto *OID = dyn_cast(DC)) return OID->getDefinition(); diff --git a/clang/test/Modules/odr_hash-enum.c b/clang/test/Modules/odr_hash-enum.c new file mode 100644 index 00..f8ede923fe2caa --- /dev/null +++ b/clang/test/Modules/odr_hash-enum.c @@ -0,0 +1,75 @@ +// Clear and create directories +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: mkdir %t/cache +// RUN: mkdir %t/Inputs + +// Build first header file +// RUN: echo "#define FIRST" >> %t/Inputs/first.h +// RUN: cat %s >> %t/Inputs/first.h + +// Build second header file +// RUN: echo "#define SECOND" >> %t/Inputs/second.h +// RUN: cat %s>> %t/Inputs/second.h + +// Test that each header can compile +// RUN: %clang_cc1 -fsyntax-only -x c %t/Inputs/first.h +// RUN: %clang_cc1 -fsyntax-only -x c %t/Inputs/second.h + +// Build module map file +// RUN: echo "module FirstModule {" >> %t/Inputs/module.modulemap +// RUN: echo "header \"first.h\"" >> %t/Inputs/module.modulemap +// RUN: echo "}">> %t/Inputs/module.modulemap +// RUN: echo "module SecondModule {">> %t/Inputs/module.modulemap +// RUN: echo "header \"second.h\"" >> %t/Inputs/module.modulemap +// RUN: echo "}">> %t/Inputs/module.modulemap + +// Run test +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c -I%t/Inputs -verify %s + +#if !defined(FIRST) && !defined(SECOND) +#include "first.h" +#include "second.h" +#endif + +#if defined(FIRST) +enum DifferentEnumConstants { kDifferentEnumConstantsValueFirst }; +#elif defined(SECOND) +enum DifferentEnumConstants { kDifferentEnumConstantsValueSecond }; +#else +enum DifferentEnumConstants differentEnumConstants; +// expected-error@second.h:* {{'kDifferentEnumConstantsValueSecond' from module 'SecondModule' is not present in definition of 'enum DifferentEnumConstants' in module 'FirstModule'}} +// expected-note@first.h:* {{definition has no member 'kDifferentEnumConstantsValueSecond'}} +#endif + +#if defined(FIRST) +enum DifferentEnumValues { kDifferentEnumValue = 0 }; +#elif defined(SECOND) +enum DifferentEnumValues { kDifferentEnumValue = 1 }; +#else +enum DifferentEnumValues differentEnumValue; +// expected-error@first.h:* {{'DifferentEnumValues' has different definitions in different modules; definition in module 'FirstModule' first difference is 1st element 'kDifferentEnumValue' has an initializer}} +// expected-note@second.h:* {{but in 'SecondModule' found 1st element 'kDifferentEnumValue' has different initializer}} +#endif + +#if defined(FIRST) +enum { +kAnonymousEnumValueFirst = 1, +}; +#elif defined(SECOND) +enum { +kAnonymousEnumValueSecond = 2, +}; +#else +// Anonymous enums don't have to match, no errors expected. +int anonymousEnumValue = kAnonymousEnumValueFirst + kAnonymousEnumValueSecond; +#endif + +// Keep macros contained to one file. +#ifdef FIRST +#undef FIRST +#endif + +#ifdef SECOND +#undef SECOND +#endif ___ cfe-commits mailing list cfe-commits@lists.llvm.org
[clang] [unused-includes] PCHContainerOperations uses MemoryBufferRef, not MemoryBuffer. NFC. (PR #88794)
https://github.com/vsapsai closed https://github.com/llvm/llvm-project/pull/88794 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [unused-includes][Serialization] Remove unused includes. NFC. (PR #88790)
https://github.com/vsapsai closed https://github.com/llvm/llvm-project/pull/88790 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [unused-includes] PCHContainerOperations uses MemoryBufferRef, not MemoryBuffer. NFC. (PR #88794)
https://github.com/vsapsai created https://github.com/llvm/llvm-project/pull/88794 None >From b95289569d0441ff799282e125e4f9ad16969f12 Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai Date: Mon, 15 Apr 2024 13:44:54 -0700 Subject: [PATCH] [unused-includes] PCHContainerOperations uses MemoryBufferRef, not MemoryBuffer. NFC. --- clang/include/clang/Serialization/PCHContainerOperations.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Serialization/PCHContainerOperations.h b/clang/include/clang/Serialization/PCHContainerOperations.h index ddfddf2dafadf9..c9a7e334ce6eb3 100644 --- a/clang/include/clang/Serialization/PCHContainerOperations.h +++ b/clang/include/clang/Serialization/PCHContainerOperations.h @@ -12,7 +12,7 @@ #include "clang/Basic/Module.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" -#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MemoryBufferRef.h" #include namespace llvm { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [unused-includes][Serialization] Remove unused includes. NFC. (PR #88790)
https://github.com/vsapsai created https://github.com/llvm/llvm-project/pull/88790 None >From 72f8208752d188aa32e9989faecd7c4b11779eb9 Mon Sep 17 00:00:00 2001 From: Volodymyr Sapsai Date: Mon, 15 Apr 2024 13:22:48 -0700 Subject: [PATCH] [unused-includes][Serialization] Remove unused includes. NFC. --- clang/include/clang/Serialization/ModuleFileExtension.h | 1 - clang/lib/Serialization/ASTReader.cpp | 1 - clang/lib/Serialization/ASTWriterDecl.cpp | 1 - clang/lib/Serialization/ASTWriterStmt.cpp | 1 - clang/lib/Serialization/GeneratePCH.cpp | 1 - clang/lib/Serialization/GlobalModuleIndex.cpp | 1 - clang/lib/Serialization/ModuleFileExtension.cpp | 2 +- clang/lib/Serialization/PCHContainerOperations.cpp | 2 -- 8 files changed, 1 insertion(+), 9 deletions(-) diff --git a/clang/include/clang/Serialization/ModuleFileExtension.h b/clang/include/clang/Serialization/ModuleFileExtension.h index d7d456c8b5db8e..50ce401516275c 100644 --- a/clang/include/clang/Serialization/ModuleFileExtension.h +++ b/clang/include/clang/Serialization/ModuleFileExtension.h @@ -9,7 +9,6 @@ #ifndef LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H #define LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/ExtensibleRTTI.h" #include "llvm/Support/HashBuilder.h" #include "llvm/Support/MD5.h" diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 8c4b460970ad2b..c68f093ebe63f6 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -31,7 +31,6 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/ODRDiagsEmitter.h" -#include "clang/AST/ODRHash.h" #include "clang/AST/OpenACCClause.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/RawCommentList.h" diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 276b6257f1d841..b8003ac2f95f8e 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -16,7 +16,6 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/ODRHash.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/SourceManager.h" diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index e3816181e2b2b9..a736a7b0ef726c 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -19,7 +19,6 @@ #include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/Token.h" -#include "clang/Sema/DeclSpec.h" #include "clang/Serialization/ASTRecordWriter.h" #include "llvm/Bitstream/BitstreamWriter.h" using namespace clang; diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index 2fece29f34487e..bed74399098d7f 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -17,7 +17,6 @@ #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/SemaConsumer.h" -#include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/Bitstream/BitstreamWriter.h" diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index dd4fc3e009050f..8a8c3cd4acb8e0 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -13,7 +13,6 @@ #include "clang/Serialization/GlobalModuleIndex.h" #include "ASTReaderInternals.h" #include "clang/Basic/FileManager.h" -#include "clang/Lex/HeaderSearch.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ModuleFile.h" #include "clang/Serialization/PCHContainerOperations.h" diff --git a/clang/lib/Serialization/ModuleFileExtension.cpp b/clang/lib/Serialization/ModuleFileExtension.cpp index 95fff41e0d7a85..729529b5fca18c 100644 --- a/clang/lib/Serialization/ModuleFileExtension.cpp +++ b/clang/lib/Serialization/ModuleFileExtension.cpp @@ -6,7 +6,7 @@ // //===--===// #include "clang/Serialization/ModuleFileExtension.h" -#include "llvm/ADT/Hashing.h" + using namespace clang; char ModuleFileExtension::ID = 0; diff --git a/clang/lib/Serialization/PCHContainerOperations.cpp b/clang/lib/Serialization/PCHContainerOperations.cpp index 56ca3394385b4f..4aedb7debcff28 100644 --- a/clang/lib/Serialization/PCHContainerOperations.cpp +++ b/clang/lib/Serialization/PCHContainerOperations.cpp @@ -12,8 +12,6 @@ #include "clang/Serialization/PCHContainerOperations.h" #include "clang/AST/ASTConsumer.h" -#include
[clang] [clang-scan-deps] Fix contention when updating `TrackingStatistic`s in hot code paths in `FileManager`. (PR #88427)
vsapsai wrote: The bigger idea is that not enabled stats should be negligibly cheap. As for me, the problem is in that not being true. Let me check how we have expensive stats all the time. Extra fixes are good but I'm concerned they help only with these specific stats while others might still cause problems in different contexts. https://github.com/llvm/llvm-project/pull/88427 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules] giving the __stddef_ headers their own modules can cause redeclaration errors with -fbuiltin-headers-in-system-modules (PR #84127)
vsapsai wrote: I'm not excited by the complexity we are moving toward with the builtin headers. But I don't have any alternatives. Given the situation we are in, I think the change is ok. But I'd like someone else to look at it as it is tricky to reason about it. No blockers from me but want more people to review the change. https://github.com/llvm/llvm-project/pull/84127 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules] Headers meant to be included multiple times can be completely invisible in clang module builds (PR #83660)
vsapsai wrote: > Sometimes it does confuse clang, at least I saw problems with a `typedef > enum` when I made an include-once header `textual`. Ok, I see. I would just consider it a bug, not a design decision. > That's correct. `#import` is an external source - often it comes from the > users of the header and not the author, and the users might not be consistent > with each other. `textual` comes from the author and a much stronger > indicator of intent. Hmm, I need to think more about it. Usually I prefer for modular builds to act like non-modular as it minimizes the surprises and allows to have a portable code. But I haven't really considered the implications of such preference. I see why you prefer to give more priority to `textual`. To give a different perspective, what if a developer wants to use a newer library, for example, ncurses. The rest of SDK expects an older version and the developer might need to do some header gymnastics to make it work. So there are cases when developers need to go against library author's intent. I'm thinking that library authors aren't able to predict all the ways their library is used, so it is useful to have some flexibility around that, even at the cost of misusing the library. But this is a general opinion, I don't have specific data about the needs to tweak libraries or the risks of a library misuse. So the opinion isn't particularly strong. https://github.com/llvm/llvm-project/pull/83660 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules] giving the __stddef_ headers their own modules can cause redeclaration errors with -fbuiltin-headers-in-system-modules (PR #84127)
@@ -7,6 +7,11 @@ *===---=== */ -#ifndef offsetof +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(offsetof) || \ +(__has_feature(modules) && !__building_module(_Builtin_stddef)) vsapsai wrote: I was thinking about `offsetof` being defined in some header, not in the intended system one. And then we [transitively] include "\_\_stddef_offsetof.h". Does it mean that in this case "\_\_stddef_offsetof.h" is processed only when building module "_Builtin_stddef"? https://github.com/llvm/llvm-project/pull/84127 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules] giving the __stddef_ headers their own modules can cause redeclaration errors with -fbuiltin-headers-in-system-modules (PR #84127)
@@ -7,6 +7,11 @@ *===---=== */ -#ifndef offsetof +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(offsetof) || \ +(__has_feature(modules) && !__building_module(_Builtin_stddef)) vsapsai wrote: What should happen when `offsetof` is defined and we are building non-`_Builtin_stddef` module? https://github.com/llvm/llvm-project/pull/84127 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules] giving the __stddef_ headers their own modules can cause redeclaration errors with -fbuiltin-headers-in-system-modules (PR #84127)
@@ -2498,9 +2498,12 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, } bool NeedsFramework = false; - // Don't add the top level headers to the builtin modules if the builtin headers - // belong to the system modules. - if (!Map.LangOpts.BuiltinHeadersInSystemModules || ActiveModule->isSubModule() || !isBuiltInModuleName(ActiveModule->Name)) + // Don't add headers to the builtin modules if the builtin headers belong to + // the system modules, with the exception of __stddef_max_align_t.h which + // always had its own module. + if (!Map.LangOpts.BuiltinHeadersInSystemModules || + !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) || + ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"})) vsapsai wrote: Should `_Builtin_stddef_wint_t` be a part of this check too? I don't know the right answer, just trying to understand. https://github.com/llvm/llvm-project/pull/84127 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules] giving the __stddef_ headers their own modules can cause redeclaration errors with -fbuiltin-headers-in-system-modules (PR #84127)
https://github.com/vsapsai commented: Still kinda confused. Have a few questions trying to improve my understanding. https://github.com/llvm/llvm-project/pull/84127 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules] giving the __stddef_ headers their own modules can cause redeclaration errors with -fbuiltin-headers-in-system-modules (PR #84127)
https://github.com/vsapsai edited https://github.com/llvm/llvm-project/pull/84127 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules] Headers meant to be included multiple times can be completely invisible in clang module builds (PR #83660)
vsapsai wrote: To clarify a little bit > [...] The "already included" state is global across all modules (which is > necessary so that non-modular headers don't get compiled into multiple > translation units and cause redeclaration errors). The necessity isn't actually true. The same definition in multiple modules shouldn't confuse clang as long as these definitions are identical. But this is a side issue. To re-iterate what this change is about: 1. `#import` implies a file is a single-include 2. Textual header in a module map implies a file is a multi-include (aka re-entrant) 3. When we have both `#import` and the header marked as textual, `#import` "wins", i.e. the file is single-include 4. You want to make that when we have both `#import` and a textual header, textual should "win", i.e. the file should be multi-include Is it correct? https://github.com/llvm/llvm-project/pull/83660 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
@@ -22,7 +58,10 @@ #define WANT_BAR 1 // expected-note{{macro was defined here}} @import config; // expected-warning{{definition of configuration macro 'WANT_BAR' has no effect on the import of 'config'; pass '-DWANT_BAR=...' on the command line to configure the module}} -// RUN: rm -rf %t -// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -DWANT_FOO=1 -emit-module -fmodule-name=config %S/Inputs/module.modulemap -// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -DWANT_FOO=1 %s -verify +//--- config_error.m vsapsai wrote: That works. I like how for other cases we have the *intention* of the test written down. And I don't think it would lead to the proliferation of "config_error2.m", "config_error3.m". https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
@@ -2006,6 +2021,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, if (auto MaybeModule = MM.getCachedModuleLoad(*Path[0].first)) { // Use the cached result, which may be nullptr. Module = *MaybeModule; +// Config macros are already checked before building a module, but they need +// to be checked at each import location in case any of the config macros +// have a new value at the current `ImportLoc`. +if (Module) + checkConfigMacros(getPreprocessor(), Module, ImportLoc); } else if (ModuleName == getLangOpts().CurrentModule) { // This is the module we're building. Module = PP->getHeaderSearchInfo().lookupModule( vsapsai wrote: Thanks for checking this case! https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
https://github.com/vsapsai approved this pull request. https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
https://github.com/vsapsai edited https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
@@ -22,7 +58,10 @@ #define WANT_BAR 1 // expected-note{{macro was defined here}} @import config; // expected-warning{{definition of configuration macro 'WANT_BAR' has no effect on the import of 'config'; pass '-DWANT_BAR=...' on the command line to configure the module}} -// RUN: rm -rf %t -// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -DWANT_FOO=1 -emit-module -fmodule-name=config %S/Inputs/module.modulemap -// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -DWANT_FOO=1 %s -verify +//--- config_error.m vsapsai wrote: I was thinking about having a more descriptive name because it's not the only way to get an error. Does "config_macro_required_not_on_command_line.m" capture the purpose of the test? https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
@@ -1,3 +1,39 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -DWANT_FOO=1 -emit-module -fmodule-name=config %t/module.modulemap +// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %t -DWANT_FOO=1 %t/config.m -verify +// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %t -DTEST_ERROR %t/config_error.m -verify + +//--- module.modulemap + +module config { + header "config.h" + config_macros [exhaustive] WANT_FOO, WANT_BAR +} + +module config_error { + header "config_error.h" + config_macros SOME_VALUE +} + +//--- config.h + +#ifdef WANT_FOO +int* foo(void); +#endif + +#ifdef WANT_BAR +char *bar(void); +#endif + +//--- config_error.h + +struct my_thing { + char buf[SOME_VALUE]; vsapsai wrote: Don't think it is worth verifying in the test but we have a diagnostic ``` error: use of undeclared identifier 'SOME_VALUE' ``` which is still useful when we have no corresponding macro defined anywhere. https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
@@ -22,7 +58,10 @@ #define WANT_BAR 1 // expected-note{{macro was defined here}} @import config; // expected-warning{{definition of configuration macro 'WANT_BAR' has no effect on the import of 'config'; pass '-DWANT_BAR=...' on the command line to configure the module}} -// RUN: rm -rf %t -// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -DWANT_FOO=1 -emit-module -fmodule-name=config %S/Inputs/module.modulemap -// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -DWANT_FOO=1 %s -verify +//--- config_error.m +#ifdef TEST_ERROR +#define SOME_VALUE 5 // expected-note{{macro was defined here}} +@import config_error; // expected-error{{could not build module}} \ + // expected-warning{{definition of configuration macro 'SOME_VALUE' has no effect on the import of 'config_error';}} vsapsai wrote: Not sure if it is worth testing the part `pass '-DSOME_VALUE=...' on the command line to configure the module` but can confirm there is an actionable recommendation here. https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
@@ -2006,6 +2021,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, if (auto MaybeModule = MM.getCachedModuleLoad(*Path[0].first)) { // Use the cached result, which may be nullptr. Module = *MaybeModule; +// Config macros are already checked before building a module, but they need +// to be checked at each import location in case any of the config macros +// have a new value at the current `ImportLoc`. +if (Module) + checkConfigMacros(getPreprocessor(), Module, ImportLoc); } else if (ModuleName == getLangOpts().CurrentModule) { // This is the module we're building. Module = PP->getHeaderSearchInfo().lookupModule( vsapsai wrote: Do we need to `checkConfigMacros` for a module in this case? It is that we have ``` if check else if no check <- comment about this block else check in the called method ``` Don't know the code good enough to tell if it is required or not, just noticed an inconsistency. https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Diagnose config_macros before building modules (PR #83641)
@@ -22,7 +58,10 @@ #define WANT_BAR 1 // expected-note{{macro was defined here}} @import config; // expected-warning{{definition of configuration macro 'WANT_BAR' has no effect on the import of 'config'; pass '-DWANT_BAR=...' on the command line to configure the module}} -// RUN: rm -rf %t -// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -DWANT_FOO=1 -emit-module -fmodule-name=config %S/Inputs/module.modulemap -// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -DWANT_FOO=1 %s -verify +//--- config_error.m +#ifdef TEST_ERROR vsapsai wrote: What is the point of wrapping everything in `TEST_ERROR`? https://github.com/llvm/llvm-project/pull/83641 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
@@ -0,0 +1,20 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/foo.cpp -I%t -fsyntax-only -verify + +//--- i.h +#ifndef FOO_H +#pragma once +struct S{}; +#endif + +//--- foo.cpp vsapsai wrote: Personally I would name the file as test.cpp but don't have a strong opinion. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
@@ -0,0 +1,20 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/foo.cpp -I%t -fsyntax-only -verify vsapsai wrote: You don't really need `-I%t`, the test works without it. But don't have a strong opinion. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
@@ -0,0 +1,20 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/foo.cpp -I%t -fsyntax-only -verify + +//--- i.h +#ifndef FOO_H vsapsai wrote: The mismatch between i.h and FOO_H is slightly annoying but don't think it is bad enough to block the change. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
@@ -1458,7 +1458,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor , } else { // Otherwise, if this is a #include of a file that was previously #import'd // or if this is the second #include of a #pragma once file, ignore it. -if ((FileInfo.isPragmaOnce || FileInfo.isImport) && !TryEnterImported()) vsapsai wrote: Technically, `TryEnterImported` can be inlined at another call site but I think it's not worth it and we can keep things the way you have in PR. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
@@ -1458,7 +1458,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor , } else { // Otherwise, if this is a #include of a file that was previously #import'd // or if this is the second #include of a #pragma once file, ignore it. vsapsai wrote: Surprisingly, the comment is more correct now. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
https://github.com/vsapsai approved this pull request. Overall, the change works fine and it is pretty small. Have a few minor suggestion for the test but nothing blocking. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
https://github.com/vsapsai edited https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
vsapsai wrote: So far the testing shows there are no regressions. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
vsapsai wrote: Started some of the tests. Expect to have results by the end of this week or early next week. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Modules] [HeaderSearch] Don't reenter headers if it is pragma once (PR #76119)
vsapsai wrote: I'll need to test this change on the real code to see the consequences. Sorry, I'll be able to do that in January only. https://github.com/llvm/llvm-project/pull/76119 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 52c62d4 - Reland "[modules] Fix error about the same module being defined in different .pcm files when using VFS overlays."
Author: Volodymyr Sapsai Date: 2023-08-16T18:27:17-07:00 New Revision: 52c62d46a0c8ebf6023233cabc5beb4ee2687c78 URL: https://github.com/llvm/llvm-project/commit/52c62d46a0c8ebf6023233cabc5beb4ee2687c78 DIFF: https://github.com/llvm/llvm-project/commit/52c62d46a0c8ebf6023233cabc5beb4ee2687c78.diff LOG: Reland "[modules] Fix error about the same module being defined in different .pcm files when using VFS overlays." Fixing Windows buildbot by not using "BuildTemporaries/module.modulemap" because it is interpreted as defining a module in "BuildTemporaries" directory. Fix errors like > module 'MultiPath' is defined in both > 'path/to/modules.cache/3JR48BPRU7BCG/MultiPath-1352QHUF8RNMU.pcm' and > 'path/to/modules.cache/3JR48BPRU7BCG/MultiPath-20HNSLLIUDDV1.pcm' To avoid building extra identical modules `-ivfsoverlay` option is not a part of the hash like "/3JR48BPRU7BCG/". And it is build system's responsibility to provide `-ivfsoverlay` options that don't cause observable differences. We also need to make sure the hash like "-1352QHUF8RNMU" is not affected by `-ivfsoverlay`. As this hash is defined by the module map path, use the path prior to any VFS remappings. rdar://111921464 Differential Revision: https://reviews.llvm.org/D156749 Added: clang/test/VFS/module-map-path.m Modified: clang/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTWriter.cpp Removed: diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index f42d51d65dcdf3..80e1bad72ce9b7 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -177,7 +177,7 @@ std::string HeaderSearch::getCachedModuleFileName(Module *Module) { // *.modulemap file. In this case, just return an empty string. if (!ModuleMap) return {}; - return getCachedModuleFileName(Module->Name, ModuleMap->getName()); + return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested()); } std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 8b0015f1ee9f6c..289c0383cd4b0e 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1327,7 +1327,8 @@ void ASTWriter::WriteControlBlock(Preprocessor , ASTContext , auto = PP.getHeaderSearchInfo().getModuleMap(); AddPath(WritingModule->PresumedModuleMapFile.empty() -? Map.getModuleMapFileForUniquing(WritingModule)->getName() +? Map.getModuleMapFileForUniquing(WritingModule) + ->getNameAsRequested() : StringRef(WritingModule->PresumedModuleMapFile), Record); diff --git a/clang/test/VFS/module-map-path.m b/clang/test/VFS/module-map-path.m new file mode 100644 index 00..bd9b961ba860ce --- /dev/null +++ b/clang/test/VFS/module-map-path.m @@ -0,0 +1,110 @@ +// Test the module map path is consistent between clang invocations when using VFS overlays. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +// Pre-populate the module cache with the modules that don't use VFS overlays. +// RUN: %clang_cc1 -fsyntax-only -F%t/Frameworks -I%t/include %t/prepopulate_module_cache.m \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache + +// Execute a compilation with VFS overlay. .pcm file path looks like /ModuleName-.pcm. +// corresponds to the compilation settings like language options. +// corresponds to the module map path. So if any of those change, we should use a diff erent module. +// But for VFS overlay we make an exception that it's not a part of to reduce the number of built .pcm files. +// Test that paths in overlays don't leak into and don't cause using 2 .pcm files for the same module. +// DEFINE: %{command} = %clang_cc1 -fsyntax-only -verify -F%t/Frameworks -I%t/include %t/test.m \ +// DEFINE:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@@g" %t/overlay.yaml.template > %t/external-names-default.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-default.yaml + +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': true,@g" %t/overlay.yaml.template > %t/external-names-true.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-true.yaml + +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': false,@g" %t/overlay.yaml.template > %t/external-names-false.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-false.yaml + +//--- prepopulate_module_cache.m +#import + +//--- test.m +// At first import multi-path modules directly, so clang decides which .pcm file they should belong to. +#import +#import + +//
[clang] fe9c332 - Revert "Reland "[modules] Fix error about the same module being defined in different .pcm files when using VFS overlays.""
Author: Volodymyr Sapsai Date: 2023-08-10T15:14:26-07:00 New Revision: fe9c332408603e50ab846c1ad8aeb705df2950b1 URL: https://github.com/llvm/llvm-project/commit/fe9c332408603e50ab846c1ad8aeb705df2950b1 DIFF: https://github.com/llvm/llvm-project/commit/fe9c332408603e50ab846c1ad8aeb705df2950b1.diff LOG: Revert "Reland "[modules] Fix error about the same module being defined in different .pcm files when using VFS overlays."" This reverts commit b070be82bb8fb4414a8a6eb4fbfc77921d89fa4b. Added: Modified: clang/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTWriter.cpp Removed: clang/test/VFS/module-map-path.m diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 80e1bad72ce9b7..f42d51d65dcdf3 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -177,7 +177,7 @@ std::string HeaderSearch::getCachedModuleFileName(Module *Module) { // *.modulemap file. In this case, just return an empty string. if (!ModuleMap) return {}; - return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested()); + return getCachedModuleFileName(Module->Name, ModuleMap->getName()); } std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 289c0383cd4b0e..8b0015f1ee9f6c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1327,8 +1327,7 @@ void ASTWriter::WriteControlBlock(Preprocessor , ASTContext , auto = PP.getHeaderSearchInfo().getModuleMap(); AddPath(WritingModule->PresumedModuleMapFile.empty() -? Map.getModuleMapFileForUniquing(WritingModule) - ->getNameAsRequested() +? Map.getModuleMapFileForUniquing(WritingModule)->getName() : StringRef(WritingModule->PresumedModuleMapFile), Record); diff --git a/clang/test/VFS/module-map-path.m b/clang/test/VFS/module-map-path.m deleted file mode 100644 index da7fb3f0089578..00 --- a/clang/test/VFS/module-map-path.m +++ /dev/null @@ -1,110 +0,0 @@ -// Test the module map path is consistent between clang invocations when using VFS overlays. - -// RUN: rm -rf %t -// RUN: split-file %s %t - -// Pre-populate the module cache with the modules that don't use VFS overlays. -// RUN: %clang_cc1 -fsyntax-only -F%/t/Frameworks -I%/t/include %t/prepopulate_module_cache.m \ -// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache - -// Execute a compilation with VFS overlay. .pcm file path looks like /ModuleName-.pcm. -// corresponds to the compilation settings like language options. -// corresponds to the module map path. So if any of those change, we should use a diff erent module. -// But for VFS overlay we make an exception that it's not a part of to reduce the number of built .pcm files. -// Test that paths in overlays don't leak into and don't cause using 2 .pcm files for the same module. -// DEFINE: %{command} = %clang_cc1 -fsyntax-only -verify -F%/t/Frameworks -I%/t/include %t/test.m \ -// DEFINE:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache -// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@@g" %t/overlay.yaml.template > %t/external-names-default.yaml -// RUN: %{command} -ivfsoverlay %t/external-names-default.yaml - -// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': true,@g" %t/overlay.yaml.template > %t/external-names-true.yaml -// RUN: %{command} -ivfsoverlay %t/external-names-true.yaml - -// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': false,@g" %t/overlay.yaml.template > %t/external-names-false.yaml -// RUN: %{command} -ivfsoverlay %t/external-names-false.yaml - -//--- prepopulate_module_cache.m -#import - -//--- test.m -// At first import multi-path modules directly, so clang decides which .pcm file they should belong to. -#import -#import - -// Then import a module from the module cache and all its transitive dependencies. -// Make sure the .pcm files loaded directly are the same as 'Redirecting' is referencing. -#import -// expected-no-diagnostics - - -//--- Frameworks/MultiPath.framework/Headers/MultiPath.h -void multiPathFramework(void); - -//--- Frameworks/MultiPath.framework/Modules/module.modulemap -framework module MultiPath { -header "MultiPath.h" -export * -} - - -//--- include/MultiPathHeader.h -void multiPathHeader(void); - -//--- include/module.modulemap -module MultiPathHeader { -header "MultiPathHeader.h" -export * -} - - -//--- Frameworks/Redirecting.framework/Headers/Redirecting.h -#import -#import - -//---
[clang] b070be8 - Reland "[modules] Fix error about the same module being defined in different .pcm files when using VFS overlays."
Author: Volodymyr Sapsai Date: 2023-08-10T14:52:49-07:00 New Revision: b070be82bb8fb4414a8a6eb4fbfc77921d89fa4b URL: https://github.com/llvm/llvm-project/commit/b070be82bb8fb4414a8a6eb4fbfc77921d89fa4b DIFF: https://github.com/llvm/llvm-project/commit/b070be82bb8fb4414a8a6eb4fbfc77921d89fa4b.diff LOG: Reland "[modules] Fix error about the same module being defined in different .pcm files when using VFS overlays." Fixing Windows buildbot by using the same separators for `-F` and `-I` paths both in VFS overlay and on command line. Fix errors like > module 'MultiPath' is defined in both > 'path/to/modules.cache/3JR48BPRU7BCG/MultiPath-1352QHUF8RNMU.pcm' and > 'path/to/modules.cache/3JR48BPRU7BCG/MultiPath-20HNSLLIUDDV1.pcm' To avoid building extra identical modules `-ivfsoverlay` option is not a part of the hash like "/3JR48BPRU7BCG/". And it is build system's responsibility to provide `-ivfsoverlay` options that don't cause observable differences. We also need to make sure the hash like "-1352QHUF8RNMU" is not affected by `-ivfsoverlay`. As this hash is defined by the module map path, use the path prior to any VFS remappings. rdar://111921464 Differential Revision: https://reviews.llvm.org/D156749 Added: clang/test/VFS/module-map-path.m Modified: clang/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTWriter.cpp Removed: diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index f42d51d65dcdf3..80e1bad72ce9b7 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -177,7 +177,7 @@ std::string HeaderSearch::getCachedModuleFileName(Module *Module) { // *.modulemap file. In this case, just return an empty string. if (!ModuleMap) return {}; - return getCachedModuleFileName(Module->Name, ModuleMap->getName()); + return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested()); } std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 8b0015f1ee9f6c..289c0383cd4b0e 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1327,7 +1327,8 @@ void ASTWriter::WriteControlBlock(Preprocessor , ASTContext , auto = PP.getHeaderSearchInfo().getModuleMap(); AddPath(WritingModule->PresumedModuleMapFile.empty() -? Map.getModuleMapFileForUniquing(WritingModule)->getName() +? Map.getModuleMapFileForUniquing(WritingModule) + ->getNameAsRequested() : StringRef(WritingModule->PresumedModuleMapFile), Record); diff --git a/clang/test/VFS/module-map-path.m b/clang/test/VFS/module-map-path.m new file mode 100644 index 00..da7fb3f0089578 --- /dev/null +++ b/clang/test/VFS/module-map-path.m @@ -0,0 +1,110 @@ +// Test the module map path is consistent between clang invocations when using VFS overlays. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +// Pre-populate the module cache with the modules that don't use VFS overlays. +// RUN: %clang_cc1 -fsyntax-only -F%/t/Frameworks -I%/t/include %t/prepopulate_module_cache.m \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache + +// Execute a compilation with VFS overlay. .pcm file path looks like /ModuleName-.pcm. +// corresponds to the compilation settings like language options. +// corresponds to the module map path. So if any of those change, we should use a diff erent module. +// But for VFS overlay we make an exception that it's not a part of to reduce the number of built .pcm files. +// Test that paths in overlays don't leak into and don't cause using 2 .pcm files for the same module. +// DEFINE: %{command} = %clang_cc1 -fsyntax-only -verify -F%/t/Frameworks -I%/t/include %t/test.m \ +// DEFINE:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@@g" %t/overlay.yaml.template > %t/external-names-default.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-default.yaml + +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': true,@g" %t/overlay.yaml.template > %t/external-names-true.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-true.yaml + +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': false,@g" %t/overlay.yaml.template > %t/external-names-false.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-false.yaml + +//--- prepopulate_module_cache.m +#import + +//--- test.m +// At first import multi-path modules directly, so clang decides which .pcm file they should belong to. +#import +#import + +// Then import a module from the
[clang] 91b10f6 - Revert "[modules] Fix error about the same module being defined in different .pcm files when using VFS overlays."
Author: Volodymyr Sapsai Date: 2023-08-10T11:27:08-07:00 New Revision: 91b10f69740ec91ca80ec45323d9807c39252334 URL: https://github.com/llvm/llvm-project/commit/91b10f69740ec91ca80ec45323d9807c39252334 DIFF: https://github.com/llvm/llvm-project/commit/91b10f69740ec91ca80ec45323d9807c39252334.diff LOG: Revert "[modules] Fix error about the same module being defined in different .pcm files when using VFS overlays." This reverts commit 97dfaf4cd27814bdf9aa9d2eafc21fdb4f76c56d. llvm-clang-x86_64-sie-win buildbot is failing with the added test. Added: Modified: clang/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTWriter.cpp Removed: clang/test/VFS/module-map-path.m diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 80e1bad72ce9b7..f42d51d65dcdf3 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -177,7 +177,7 @@ std::string HeaderSearch::getCachedModuleFileName(Module *Module) { // *.modulemap file. In this case, just return an empty string. if (!ModuleMap) return {}; - return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested()); + return getCachedModuleFileName(Module->Name, ModuleMap->getName()); } std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 289c0383cd4b0e..8b0015f1ee9f6c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1327,8 +1327,7 @@ void ASTWriter::WriteControlBlock(Preprocessor , ASTContext , auto = PP.getHeaderSearchInfo().getModuleMap(); AddPath(WritingModule->PresumedModuleMapFile.empty() -? Map.getModuleMapFileForUniquing(WritingModule) - ->getNameAsRequested() +? Map.getModuleMapFileForUniquing(WritingModule)->getName() : StringRef(WritingModule->PresumedModuleMapFile), Record); diff --git a/clang/test/VFS/module-map-path.m b/clang/test/VFS/module-map-path.m deleted file mode 100644 index 0f3c0a7aa499eb..00 --- a/clang/test/VFS/module-map-path.m +++ /dev/null @@ -1,110 +0,0 @@ -// Test the module map path is consistent between clang invocations when using VFS overlays. - -// RUN: rm -rf %t -// RUN: split-file %s %t - -// Pre-populate the module cache with the modules that don't use VFS overlays. -// RUN: %clang_cc1 -fsyntax-only -F%t/Frameworks -I%t/include %t/prepopulate_module_cache.m \ -// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache - -// Execute a compilation with VFS overlay. .pcm file path looks like /ModuleName-.pcm. -// corresponds to the compilation settings like language options. -// corresponds to the module map path. So if any of those change, we should use a diff erent module. -// But for VFS overlay we make an exception that it's not a part of to reduce the number of built .pcm files. -// Test that paths in overlays don't leak into and don't cause using 2 .pcm files for the same module. -// DEFINE: %{command} = %clang_cc1 -fsyntax-only -verify -F%t/Frameworks -I%t/include %t/test.m \ -// DEFINE:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache -// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@@g" %t/overlay.yaml.template > %t/external-names-default.yaml -// RUN: %{command} -ivfsoverlay %t/external-names-default.yaml - -// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': true,@g" %t/overlay.yaml.template > %t/external-names-true.yaml -// RUN: %{command} -ivfsoverlay %t/external-names-true.yaml - -// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': false,@g" %t/overlay.yaml.template > %t/external-names-false.yaml -// RUN: %{command} -ivfsoverlay %t/external-names-false.yaml - -//--- prepopulate_module_cache.m -#import - -//--- test.m -// At first import multi-path modules directly, so clang decides which .pcm file they should belong to. -#import -#import - -// Then import a module from the module cache and all its transitive dependencies. -// Make sure the .pcm files loaded directly are the same as 'Redirecting' is referencing. -#import -// expected-no-diagnostics - - -//--- Frameworks/MultiPath.framework/Headers/MultiPath.h -void multiPathFramework(void); - -//--- Frameworks/MultiPath.framework/Modules/module.modulemap -framework module MultiPath { -header "MultiPath.h" -export * -} - - -//--- include/MultiPathHeader.h -void multiPathHeader(void); - -//--- include/module.modulemap -module MultiPathHeader { -header "MultiPathHeader.h" -export * -} - - -//--- Frameworks/Redirecting.framework/Headers/Redirecting.h -#import -#import -
[clang] 97dfaf4 - [modules] Fix error about the same module being defined in different .pcm files when using VFS overlays.
Author: Volodymyr Sapsai Date: 2023-08-10T10:47:51-07:00 New Revision: 97dfaf4cd27814bdf9aa9d2eafc21fdb4f76c56d URL: https://github.com/llvm/llvm-project/commit/97dfaf4cd27814bdf9aa9d2eafc21fdb4f76c56d DIFF: https://github.com/llvm/llvm-project/commit/97dfaf4cd27814bdf9aa9d2eafc21fdb4f76c56d.diff LOG: [modules] Fix error about the same module being defined in different .pcm files when using VFS overlays. Fix errors like > module 'MultiPath' is defined in both > 'path/to/modules.cache/3JR48BPRU7BCG/MultiPath-1352QHUF8RNMU.pcm' and > 'path/to/modules.cache/3JR48BPRU7BCG/MultiPath-20HNSLLIUDDV1.pcm' To avoid building extra identical modules `-ivfsoverlay` option is not a part of the hash like "/3JR48BPRU7BCG/". And it is build system's responsibility to provide `-ivfsoverlay` options that don't cause observable differences. We also need to make sure the hash like "-1352QHUF8RNMU" is not affected by `-ivfsoverlay`. As this hash is defined by the module map path, use the path prior to any VFS remappings. rdar://111921464 Differential Revision: https://reviews.llvm.org/D156749 Added: clang/test/VFS/module-map-path.m Modified: clang/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTWriter.cpp Removed: diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index f42d51d65dcdf3..80e1bad72ce9b7 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -177,7 +177,7 @@ std::string HeaderSearch::getCachedModuleFileName(Module *Module) { // *.modulemap file. In this case, just return an empty string. if (!ModuleMap) return {}; - return getCachedModuleFileName(Module->Name, ModuleMap->getName()); + return getCachedModuleFileName(Module->Name, ModuleMap->getNameAsRequested()); } std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName, diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 8b0015f1ee9f6c..289c0383cd4b0e 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1327,7 +1327,8 @@ void ASTWriter::WriteControlBlock(Preprocessor , ASTContext , auto = PP.getHeaderSearchInfo().getModuleMap(); AddPath(WritingModule->PresumedModuleMapFile.empty() -? Map.getModuleMapFileForUniquing(WritingModule)->getName() +? Map.getModuleMapFileForUniquing(WritingModule) + ->getNameAsRequested() : StringRef(WritingModule->PresumedModuleMapFile), Record); diff --git a/clang/test/VFS/module-map-path.m b/clang/test/VFS/module-map-path.m new file mode 100644 index 00..0f3c0a7aa499eb --- /dev/null +++ b/clang/test/VFS/module-map-path.m @@ -0,0 +1,110 @@ +// Test the module map path is consistent between clang invocations when using VFS overlays. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +// Pre-populate the module cache with the modules that don't use VFS overlays. +// RUN: %clang_cc1 -fsyntax-only -F%t/Frameworks -I%t/include %t/prepopulate_module_cache.m \ +// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache + +// Execute a compilation with VFS overlay. .pcm file path looks like /ModuleName-.pcm. +// corresponds to the compilation settings like language options. +// corresponds to the module map path. So if any of those change, we should use a diff erent module. +// But for VFS overlay we make an exception that it's not a part of to reduce the number of built .pcm files. +// Test that paths in overlays don't leak into and don't cause using 2 .pcm files for the same module. +// DEFINE: %{command} = %clang_cc1 -fsyntax-only -verify -F%t/Frameworks -I%t/include %t/test.m \ +// DEFINE:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@@g" %t/overlay.yaml.template > %t/external-names-default.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-default.yaml + +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': true,@g" %t/overlay.yaml.template > %t/external-names-true.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-true.yaml + +// RUN: sed -e "s@TMP_DIR@%{/t:regex_replacement}@g" -e "s@USE_EXTERNAL_NAMES_OPTION@'use-external-names': false,@g" %t/overlay.yaml.template > %t/external-names-false.yaml +// RUN: %{command} -ivfsoverlay %t/external-names-false.yaml + +//--- prepopulate_module_cache.m +#import + +//--- test.m +// At first import multi-path modules directly, so clang decides which .pcm file they should belong to. +#import +#import + +// Then import a module from the module cache and all its transitive dependencies. +// Make sure the .pcm files loaded directly are the same as 'Redirecting' is
[clang] 32056aa - [docs] Fix doxygen markers for grouping methods. NFC.
Author: Volodymyr Sapsai Date: 2023-08-03T11:16:42-07:00 New Revision: 32056aa3443786822963e6e469d98deb7b857d79 URL: https://github.com/llvm/llvm-project/commit/32056aa3443786822963e6e469d98deb7b857d79 DIFF: https://github.com/llvm/llvm-project/commit/32056aa3443786822963e6e469d98deb7b857d79.diff LOG: [docs] Fix doxygen markers for grouping methods. NFC. Added: Modified: clang/include/clang/Frontend/CompilerInstance.h Removed: diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index c6af1fd5dd010f..377055e8f6f924 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -189,7 +189,7 @@ class CompilerInstance : public ModuleLoader { ~CompilerInstance() override; /// @name High-Level Operations - /// { + /// @{ /// ExecuteAction - Execute the provided action against the compiler's /// CompilerInvocation object. @@ -223,9 +223,9 @@ class CompilerInstance : public ModuleLoader { /// Load the list of plugins requested in the \c FrontendOptions. void LoadRequestedPlugins(); - /// } + /// @} /// @name Compiler Invocation and Options - /// { + /// @{ bool hasInvocation() const { return Invocation != nullptr; } @@ -248,9 +248,9 @@ class CompilerInstance : public ModuleLoader { BuildGlobalModuleIndex = Build; } - /// } + /// @} /// @name Forwarding Methods - /// { + /// @{ AnalyzerOptionsRef getAnalyzerOpts() { return Invocation->getAnalyzerOpts(); @@ -329,9 +329,9 @@ class CompilerInstance : public ModuleLoader { return Invocation->getTargetOpts(); } - /// } + /// @} /// @name Diagnostics Engine - /// { + /// @{ bool hasDiagnostics() const { return Diagnostics != nullptr; } @@ -355,9 +355,9 @@ class CompilerInstance : public ModuleLoader { return *Diagnostics->getClient(); } - /// } + /// @} /// @name VerboseOutputStream - /// } + /// @{ /// Replace the current stream for verbose output. void setVerboseOutputStream(raw_ostream ); @@ -370,9 +370,9 @@ class CompilerInstance : public ModuleLoader { return *VerboseOutputStream; } - /// } + /// @} /// @name Target Info - /// { + /// @{ bool hasTarget() const { return Target != nullptr; } @@ -389,9 +389,9 @@ class CompilerInstance : public ModuleLoader { /// Replace the current Target. void setTarget(TargetInfo *Value); - /// } + /// @} /// @name AuxTarget Info - /// { + /// @{ TargetInfo *getAuxTarget() const { return AuxTarget.get(); } @@ -401,15 +401,15 @@ class CompilerInstance : public ModuleLoader { // Create Target and AuxTarget based on current options bool createTarget(); - /// } + /// @} /// @name Virtual File System - /// { + /// @{ llvm::vfs::FileSystem () const; - /// } + /// @} /// @name File Manager - /// { + /// @{ bool hasFileManager() const { return FileMgr != nullptr; } @@ -432,9 +432,9 @@ class CompilerInstance : public ModuleLoader { /// Replace the current file manager and virtual file system. void setFileManager(FileManager *Value); - /// } + /// @} /// @name Source Manager - /// { + /// @{ bool hasSourceManager() const { return SourceMgr != nullptr; } @@ -457,9 +457,9 @@ class CompilerInstance : public ModuleLoader { /// setSourceManager - Replace the current source manager. void setSourceManager(SourceManager *Value); - /// } + /// @} /// @name Preprocessor - /// { + /// @{ bool hasPreprocessor() const { return PP != nullptr; } @@ -478,9 +478,9 @@ class CompilerInstance : public ModuleLoader { /// Replace the current preprocessor. void setPreprocessor(std::shared_ptr Value); - /// } + /// @} /// @name ASTContext - /// { + /// @{ bool hasASTContext() const { return Context != nullptr; } @@ -506,9 +506,9 @@ class CompilerInstance : public ModuleLoader { /// of S. void setSema(Sema *S); - /// } + /// @} /// @name ASTConsumer - /// { + /// @{ bool hasASTConsumer() const { return (bool)Consumer; } @@ -525,9 +525,9 @@ class CompilerInstance : public ModuleLoader { /// takes ownership of \p Value. void setASTConsumer(std::unique_ptr Value); - /// } + /// @} /// @name Semantic analysis - /// { + /// @{ bool hasSema() const { return (bool)TheSema; } Sema () const { @@ -538,9 +538,9 @@ class CompilerInstance : public ModuleLoader { std::unique_ptr takeSema(); void resetAndLeakSema(); - /// } + /// @} /// @name Module Management - /// { + /// @{ IntrusiveRefCntPtr getASTReader() const; void setASTReader(IntrusiveRefCntPtr Reader); @@ -581,9 +581,9 @@ class CompilerInstance : public ModuleLoader { return *Reader; } - /// } + /// @} /// @name Code Completion - /// { + /// @{ bool
[clang] d1e8df8 - [clang] Fix a typo "mdoule" in comments. NFC.
Author: Volodymyr Sapsai Date: 2023-07-06T17:19:26-07:00 New Revision: d1e8df85e6d1f9f823f2de5e0eb88d9a08d1763f URL: https://github.com/llvm/llvm-project/commit/d1e8df85e6d1f9f823f2de5e0eb88d9a08d1763f DIFF: https://github.com/llvm/llvm-project/commit/d1e8df85e6d1f9f823f2de5e0eb88d9a08d1763f.diff LOG: [clang] Fix a typo "mdoule" in comments. NFC. Added: Modified: clang/include/clang/Serialization/ModuleFile.h clang/test/CodeGenCXX/modules-vtable.cppm Removed: diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h index 45fb75df8a4352..e96f3ce06c2ceb 100644 --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -164,7 +164,7 @@ class ModuleFile { /// Whether this precompiled header is a relocatable PCH file. bool RelocatablePCH = false; - /// Whether this mdoule file is a standard c++ module. + /// Whether this module file is a standard C++ module. bool StandardCXXModule = false; /// Whether timestamps are included in this module file. diff --git a/clang/test/CodeGenCXX/modules-vtable.cppm b/clang/test/CodeGenCXX/modules-vtable.cppm index 5d13225697b4da..fb179b1de4880b 100644 --- a/clang/test/CodeGenCXX/modules-vtable.cppm +++ b/clang/test/CodeGenCXX/modules-vtable.cppm @@ -68,7 +68,7 @@ int use() { // Check the case that the declaration of the key function comes from another // module unit but the definition of the key function comes from the current -// mdoule unit. +// module unit. //--- M-A.cppm export module M:A; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] f7e0aae - [ODRHash] Stop hashing `ObjCMethodDecl::isPropertyAccessor` as it doesn't capture inherent method quality.
Author: Volodymyr Sapsai Date: 2023-07-05T18:04:50-07:00 New Revision: f7e0aae7284b7ad0cf3cc277c5ef8731f564443d URL: https://github.com/llvm/llvm-project/commit/f7e0aae7284b7ad0cf3cc277c5ef8731f564443d DIFF: https://github.com/llvm/llvm-project/commit/f7e0aae7284b7ad0cf3cc277c5ef8731f564443d.diff LOG: [ODRHash] Stop hashing `ObjCMethodDecl::isPropertyAccessor` as it doesn't capture inherent method quality. `isPropertyAccessor` depends on the surrounding code and not on the method itself. That's why it can be different in different modules. And mismatches shouldn't be an error. rdar://109481753 Differential Revision: https://reviews.llvm.org/D154460 Added: Modified: clang/lib/AST/ODRHash.cpp clang/test/Modules/compare-objc-nonisolated-methods.m Removed: diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 3ea023d3cee66a..507fb0b49f8ad3 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -373,7 +373,6 @@ class ODRDeclVisitor : public ConstDeclVisitor { void VisitObjCMethodDecl(const ObjCMethodDecl *Method) { ID.AddInteger(Method->getDeclKind()); Hash.AddBoolean(Method->isInstanceMethod()); // false if class method -Hash.AddBoolean(Method->isPropertyAccessor()); Hash.AddBoolean(Method->isVariadic()); Hash.AddBoolean(Method->isSynthesizedAccessorStub()); Hash.AddBoolean(Method->isDefined()); diff --git a/clang/test/Modules/compare-objc-nonisolated-methods.m b/clang/test/Modules/compare-objc-nonisolated-methods.m index a60114148420bd..41e861547af420 100644 --- a/clang/test/Modules/compare-objc-nonisolated-methods.m +++ b/clang/test/Modules/compare-objc-nonisolated-methods.m @@ -5,12 +5,17 @@ // is not an error because it depends on the surrounding code and not on the method itself. // RUN: %clang_cc1 -fsyntax-only -verify -I%t/include -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache -fmodule-name=Override %t/test-overriding.m +// Test that diff erent values of `ObjCMethodDecl::isPropertyAccessor` in diff erent modules +// is not an error because it depends on the surrounding code and not on the method itself. +// RUN: %clang_cc1 -fsyntax-only -verify -I%t/include -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache -fmodule-name=PropertyAccessor %t/test-property_accessor.m + //--- include/Common.h @interface NSObject @end //--- include/Indirection.h #import +#import //--- include/module.modulemap module Common { @@ -25,6 +30,10 @@ @interface NSObject header "Override.h" export * } +module PropertyAccessor { + header "PropertyAccessor.h" + export * +} //--- include/Override.h #import @@ -52,3 +61,31 @@ - (void)potentialOverride; void triggerOverrideCheck(SubClass *sc) { [sc potentialOverride]; } + +//--- include/PropertyAccessor.h +#import +@interface PropertySubClass: NSObject +- (int)potentialProperty; +- (void)setPotentialProperty:(int)p; +@end + +//--- PropertyAccessor_Internal.h +#import +@interface PropertySubClass() +@property int potentialProperty; +@end + +//--- test-property_accessor.m +//expected-no-diagnostics +// Get a version of `PropertySubClass` where `-[PropertySubClass potentialProperty]` +// is a property accessor. +#import "PropertyAccessor_Internal.h" + +// Get a version of `PropertySubClass` where `-[PropertySubClass potentialProperty]` +// is not a property accessor because module "PropertyAccessor" doesn't know about PropertyAccessor_Internal.h. +#import + +void triggerPropertyAccessorCheck(PropertySubClass *x) { + int tmp = [x potentialProperty]; + [x setPotentialProperty: tmp]; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 18530e5 - [ODRHash] Stop hashing `ObjCMethodDecl::isOverriding` as it doesn't capture inherent method quality.
Author: Volodymyr Sapsai Date: 2023-07-05T18:04:32-07:00 New Revision: 18530e5d0770098bc33ff6f02a7b63ea887692a6 URL: https://github.com/llvm/llvm-project/commit/18530e5d0770098bc33ff6f02a7b63ea887692a6 DIFF: https://github.com/llvm/llvm-project/commit/18530e5d0770098bc33ff6f02a7b63ea887692a6.diff LOG: [ODRHash] Stop hashing `ObjCMethodDecl::isOverriding` as it doesn't capture inherent method quality. `isOverriding` depends on the surrounding code and not on the method itself. That's why it can be different in different modules. And mismatches shouldn't be an error. rdar://109481753 Differential Revision: https://reviews.llvm.org/D154459 Added: clang/test/Modules/compare-objc-nonisolated-methods.m Modified: clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/AST/ODRHash.cpp Removed: diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp b/clang/lib/AST/ODRDiagsEmitter.cpp index d1c59bd1f2ca23..1994f0865428bd 100644 --- a/clang/lib/AST/ODRDiagsEmitter.cpp +++ b/clang/lib/AST/ODRDiagsEmitter.cpp @@ -2096,7 +2096,8 @@ bool ODRDiagsEmitter::diagnoseMismatch( << FirstDecl->getSourceRange(); Diag(SecondDecl->getLocation(), diag::note_module_odr_violation_mismatch_decl_unknown) - << SecondModule << FirstDiffType << SecondDecl->getSourceRange(); + << SecondModule.empty() << SecondModule << FirstDiffType + << SecondDecl->getSourceRange(); return true; } diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 0ead0940479d85..3ea023d3cee66a 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -377,7 +377,6 @@ class ODRDeclVisitor : public ConstDeclVisitor { Hash.AddBoolean(Method->isVariadic()); Hash.AddBoolean(Method->isSynthesizedAccessorStub()); Hash.AddBoolean(Method->isDefined()); -Hash.AddBoolean(Method->isOverriding()); Hash.AddBoolean(Method->isDirectMethod()); Hash.AddBoolean(Method->isThisDeclarationADesignatedInitializer()); Hash.AddBoolean(Method->hasSkippedBody()); diff --git a/clang/test/Modules/compare-objc-nonisolated-methods.m b/clang/test/Modules/compare-objc-nonisolated-methods.m new file mode 100644 index 00..a60114148420bd --- /dev/null +++ b/clang/test/Modules/compare-objc-nonisolated-methods.m @@ -0,0 +1,54 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// Test that diff erent values of `ObjCMethodDecl::isOverriding` in diff erent modules +// is not an error because it depends on the surrounding code and not on the method itself. +// RUN: %clang_cc1 -fsyntax-only -verify -I%t/include -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache -fmodule-name=Override %t/test-overriding.m + +//--- include/Common.h +@interface NSObject +@end + +//--- include/Indirection.h +#import + +//--- include/module.modulemap +module Common { + header "Common.h" + export * +} +module Indirection { + header "Indirection.h" + export * +} +module Override { + header "Override.h" + export * +} + +//--- include/Override.h +#import +@interface SubClass: NSObject +- (void)potentialOverride; +@end + +//--- Override_Internal.h +#import +@interface NSObject(InternalCategory) +- (void)potentialOverride; +@end + +//--- test-overriding.m +//expected-no-diagnostics +// Get non-modular version of `SubClass`, so that `-[SubClass potentialOverride]` +// is an override of a method in `InternalCategory`. +#import "Override_Internal.h" +#import + +// Get modular version of `SubClass` where `-[SubClass potentialOverride]` is +// not an override because module "Override" doesn't know about Override_Internal.h. +#import + +void triggerOverrideCheck(SubClass *sc) { + [sc potentialOverride]; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 2e16df3 - [ASTStructuralEquivalence] Fix crash when ObjCCategoryDecl doesn't have corresponding ObjCInterfaceDecl.
Author: Volodymyr Sapsai Date: 2023-06-09T17:09:28-07:00 New Revision: 2e16df352c7acb910313c80ac90b650ad9c14a3d URL: https://github.com/llvm/llvm-project/commit/2e16df352c7acb910313c80ac90b650ad9c14a3d DIFF: https://github.com/llvm/llvm-project/commit/2e16df352c7acb910313c80ac90b650ad9c14a3d.diff LOG: [ASTStructuralEquivalence] Fix crash when ObjCCategoryDecl doesn't have corresponding ObjCInterfaceDecl. When this happens, it is invalid code and there is diagnostic ``` error: cannot find interface declaration for '...' ``` But clang shouldn't crash even if code is invalid. Though subsequent diagnostic can be imperfect because without ObjCInterfaceDecl we don't have a type for error messages. rdar://108818430 Differential Revision: https://reviews.llvm.org/D151523 Added: Modified: clang/lib/AST/ASTStructuralEquivalence.cpp clang/unittests/AST/StructuralEquivalenceTest.cpp Removed: diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index a9470782c634e..f867b6bf84beb 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -2057,8 +2057,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier())) return false; - if (!IsStructurallyEquivalent(D1->getClassInterface()->getIdentifier(), -D2->getClassInterface()->getIdentifier())) + const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(), + *Intf2 = D2->getClassInterface(); + if ((!Intf1 || !Intf2) && (Intf1 != Intf2)) +return false; + + if (Intf1 && + !IsStructurallyEquivalent(Intf1->getIdentifier(), Intf2->getIdentifier())) return false; // Compare protocols. @@ -2077,7 +2082,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , return false; // Compare ivars. - QualType D2Type = Context.ToCtx.getObjCInterfaceType(D2->getClassInterface()); + QualType D2Type = + Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) : QualType(); ObjCCategoryDecl::ivar_iterator Ivar2 = D2->ivar_begin(), Ivar2End = D2->ivar_end(); for (ObjCCategoryDecl::ivar_iterator Ivar1 = D1->ivar_begin(), diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 8efb9a905c2f1..319eefe1e6ba3 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -1143,6 +1143,18 @@ TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithDifferentNames) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithoutInterfaces) { + auto t = makeDecls(" @interface A(X) @end", + "@interface A @end @interface A(X) @end", + Lang_OBJC, objcCategoryDecl()); + EXPECT_FALSE(testStructuralMatch(t)); + + auto t2 = makeDecls("@interface A(X) @end", +"@interface A(X) @end", +Lang_OBJC, objcCategoryDecl()); + EXPECT_TRUE(testStructuralMatch(t2)); +} + TEST_F(StructuralEquivalenceObjCCategoryTest, CategoryAndExtension) { auto t = makeDecls("@interface A @end @interface A(X) @end", "@interface A @end @interface A() @end", ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 24f36a2 - [Modules] Move modulemaps to header search directories. NFC intended.
Author: Volodymyr Sapsai Date: 2023-05-03T13:07:47-07:00 New Revision: 24f36a215b4eabd1d0e4abcce0c9277085d88a96 URL: https://github.com/llvm/llvm-project/commit/24f36a215b4eabd1d0e4abcce0c9277085d88a96 DIFF: https://github.com/llvm/llvm-project/commit/24f36a215b4eabd1d0e4abcce0c9277085d88a96.diff LOG: [Modules] Move modulemaps to header search directories. NFC intended. In code we use `#include "llvm/Lib/Header.h"` which is located in "llvm/include/llvm/Lib/Header.h", so we use "llvm/include/" as a header search path. We should put modulemaps in the same directory and shouldn't rely on clang to search in immediate subdirectories. rdar://106677321 Differential Revision: https://reviews.llvm.org/D148776 Added: clang/include/module.modulemap lldb/include/module.modulemap llvm/include/CMakeLists.txt llvm/include/module.extern.modulemap llvm/include/module.install.modulemap llvm/include/module.modulemap llvm/include/module.modulemap.build Modified: llvm/CMakeLists.txt llvm/include/llvm/CMakeLists.txt Removed: clang/include/clang-c/module.modulemap clang/include/clang/module.modulemap lldb/include/lldb/module.modulemap llvm/include/llvm-c/module.modulemap llvm/include/llvm/module.extern.modulemap llvm/include/llvm/module.install.modulemap llvm/include/llvm/module.modulemap llvm/include/llvm/module.modulemap.build diff --git a/clang/include/clang-c/module.modulemap b/clang/include/clang-c/module.modulemap deleted file mode 100644 index 95a59d62344cc..0 --- a/clang/include/clang-c/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -module Clang_C { - umbrella "." - module * { export * } -} diff --git a/clang/include/clang/module.modulemap b/clang/include/clang/module.modulemap deleted file mode 100644 index 624045dc4c57b..0 --- a/clang/include/clang/module.modulemap +++ /dev/null @@ -1,199 +0,0 @@ -module Clang_Analysis { - requires cplusplus - umbrella "Analysis" - - textual header "Analysis/Analyses/ThreadSafetyOps.def" - - module * { export * } - - // FIXME: Exclude these headers to avoid pulling all of the AST matchers - // library into clang. Due to inline key functions in the headers, - // importing the AST matchers library gives a link dependency on the AST - // matchers (and thus the AST), which clang-format should not have. - exclude header "Analysis/Analyses/ExprMutationAnalyzer.h" -} - -module Clang_AST { - requires cplusplus - umbrella "AST" - - textual header "AST/BuiltinTypes.def" - textual header "AST/CXXRecordDeclDefinitionBits.def" - textual header "AST/OperationKinds.def" - textual header "AST/TypeLocNodes.def" - - module * { export * } -} - -module Clang_ASTMatchers { requires cplusplus umbrella "ASTMatchers" module * { export * } } - -module Clang_Basic { - requires cplusplus - umbrella "Basic" - - textual header "Basic/AArch64SVEACLETypes.def" - textual header "Basic/BuiltinsAArch64.def" - textual header "Basic/BuiltinsAMDGPU.def" - textual header "Basic/BuiltinsAArch64NeonSVEBridge.def" - textual header "Basic/BuiltinsAArch64NeonSVEBridge_cg.def" - textual header "Basic/BuiltinsARM.def" - textual header "Basic/BuiltinsBPF.def" - textual header "Basic/Builtins.def" - textual header "Basic/BuiltinHeaders.def" - textual header "Basic/BuiltinsHexagon.def" - textual header "Basic/BuiltinsHexagonDep.def" - textual header "Basic/BuiltinsHexagonMapCustomDep.def" - textual header "Basic/BuiltinsLoongArch.def" - textual header "Basic/BuiltinsMips.def" - textual header "Basic/BuiltinsNEON.def" - textual header "Basic/BuiltinsNVPTX.def" - textual header "Basic/BuiltinsPPC.def" - textual header "Basic/BuiltinsRISCV.def" - textual header "Basic/BuiltinsRISCVVector.def" - textual header "Basic/BuiltinsSVE.def" - textual header "Basic/BuiltinsSystemZ.def" - textual header "Basic/BuiltinsVE.def" - textual header "Basic/BuiltinsVEVL.gen.def" - textual header "Basic/BuiltinsWebAssembly.def" - textual header "Basic/BuiltinsX86.def" - textual header "Basic/BuiltinsX86_64.def" - textual header "Basic/BuiltinsXCore.def" - textual header "Basic/CodeGenOptions.def" - textual header "Basic/DiagnosticOptions.def" - textual header "Basic/Features.def" - textual header "Basic/FPOptions.def" - textual header "Basic/MSP430Target.def" - textual header "Basic/LangOptions.def" - textual header "Basic/OpenCLExtensions.def" - textual header "Basic/OpenCLImageTypes.def" - textual header "Basic/OpenCLExtensionTypes.def" - textual header "Basic/OpenMPKinds.def" - textual header "Basic/OperatorKinds.def" - textual header "Basic/PPCTypes.def" - textual header "Basic/RISCVVTypes.def" - textual header "Basic/Sanitizers.def" - textual header "Basic/TargetCXXABI.def" - textual header "Basic/TransformTypeTraits.def" - textual header "Basic/TokenKinds.def" - textual header
[clang] e46aa7f - Fix a typo in head comment of `CurPPLexer`.
Author: Zhouyi Zhou Date: 2023-05-02T19:49:21-07:00 New Revision: e46aa7f927293989dae40817c0087cba9cf5fae7 URL: https://github.com/llvm/llvm-project/commit/e46aa7f927293989dae40817c0087cba9cf5fae7 DIFF: https://github.com/llvm/llvm-project/commit/e46aa7f927293989dae40817c0087cba9cf5fae7.diff LOG: Fix a typo in head comment of `CurPPLexer`. In head comment of CurPPLexer field of class Preprocessor, 'The current top of the stack what we're lexing from' should be 'The current top of the stack that we're lexing from'. Differential Revision: https://reviews.llvm.org/D149709 Added: Modified: clang/include/clang/Lex/Preprocessor.h Removed: diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index a34a451f4bad1..8bdaf25e9b870 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -729,7 +729,7 @@ class Preprocessor { /// Only one of CurLexer, or CurTokenLexer will be non-null. std::unique_ptr CurLexer; - /// The current top of the stack what we're lexing from + /// The current top of the stack that we're lexing from /// if not expanding a macro. /// /// This is an alias for CurLexer. ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] a845aeb - [Driver] Allow to collect `-save-stats` data to a file specified in the environment variable.
Author: Volodymyr Sapsai Date: 2023-03-16T11:57:59-07:00 New Revision: a845aeb5d6c869146fa24194a7d0182a4787cad8 URL: https://github.com/llvm/llvm-project/commit/a845aeb5d6c869146fa24194a7d0182a4787cad8 DIFF: https://github.com/llvm/llvm-project/commit/a845aeb5d6c869146fa24194a7d0182a4787cad8.diff LOG: [Driver] Allow to collect `-save-stats` data to a file specified in the environment variable. Using two environment variables `CC_PRINT_INTERNAL_STAT` and `CC_PRINT_INTERNAL_STAT_FILE` to work like `CC_PRINT_PROC_STAT`. The purpose of the change is to allow collecting the internal stats without modifying the build scripts. Write all stats to a single file to simplify aggregating the data. Differential Revision: https://reviews.llvm.org/D144981 Added: Modified: clang/docs/CommandGuide/clang.rst clang/include/clang/Driver/Driver.h clang/include/clang/Driver/Options.td clang/include/clang/Frontend/FrontendOptions.h clang/lib/Driver/Driver.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Driver/ToolChains/CommonArgs.cpp clang/lib/Frontend/CompilerInstance.cpp clang/test/Driver/save-stats.c clang/tools/driver/driver.cpp Removed: diff --git a/clang/docs/CommandGuide/clang.rst b/clang/docs/CommandGuide/clang.rst index e076818697eb1..0722979885afb 100644 --- a/clang/docs/CommandGuide/clang.rst +++ b/clang/docs/CommandGuide/clang.rst @@ -598,6 +598,16 @@ Driver Options directory (:option:`-save-stats`/"-save-stats=cwd") or the directory of the output file ("-save-state=obj"). + You can also use environment variables to control the statistics reporting. + Setting ``CC_PRINT_INTERNAL_STAT`` to ``1`` enables the feature, the report + goes to stdout in JSON format. + + Setting ``CC_PRINT_INTERNAL_STAT_FILE`` to a file path makes it report + statistics to the given file in the JSON format. + + Note that ``-save-stats`` take precedence over ``CC_PRINT_INTERNAL_STAT`` + and ``CC_PRINT_INTERNAL_STAT_FILE``. + .. option:: -integrated-as, -no-integrated-as Used to enable and disable, respectively, the use of the integrated diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index c85658d7c56e3..e3e98bad99127 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -194,6 +194,9 @@ class Driver { /// The file to log CC_PRINT_PROC_STAT_FILE output to, if enabled. std::string CCPrintStatReportFilename; + /// The file to log CC_PRINT_INTERNAL_STAT_FILE output to, if enabled. + std::string CCPrintInternalStatReportFilename; + /// The file to log CC_PRINT_OPTIONS output to, if enabled. std::string CCPrintOptionsFilename; @@ -258,6 +261,10 @@ class Driver { /// performance report to CC_PRINT_PROC_STAT_FILE or to stdout. unsigned CCPrintProcessStats : 1; + /// Set CC_PRINT_INTERNAL_STAT mode, which causes the driver to dump internal + /// performance report to CC_PRINT_INTERNAL_STAT_FILE or to stdout. + unsigned CCPrintInternalStats : 1; + /// Pointer to the ExecuteCC1Tool function, if available. /// When the clangDriver lib is used through clang.exe, this provides a /// shortcut for executing the -cc1 command-line directly, in the same diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index a2dbef1cc7cfe..a05e61ac0e92f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6147,6 +6147,9 @@ def print_stats : Flag<["-"], "print-stats">, def stats_file : Joined<["-"], "stats-file=">, HelpText<"Filename to write statistics to">, MarshallingInfoString>; +def stats_file_append : Flag<["-"], "stats-file-append">, + HelpText<"If stats should be appended to stats-file instead of overwriting it">, + MarshallingInfoFlag>; def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">, HelpText<"Dump record layout information in a simple form used for testing">, MarshallingInfoFlag>; diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index ef04f3b236d87..85183a3812b42 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -278,6 +278,8 @@ class FrontendOptions { /// Show frontend performance metrics and statistics. unsigned ShowStats : 1; + unsigned AppendStats : 1; + /// print the supported cpus for the current target unsigned PrintSupportedCPUs : 1; @@ -511,16 +513,16 @@ class FrontendOptions { public: FrontendOptions() : DisableFree(false), RelocatablePCH(false), ShowHelp(false), -ShowStats(false), TimeTrace(false), ShowVersion(false), -FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), -FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), -
[clang] 2893d55 - [Serialization] Don't warn when a deserialized category is equivalent to an existing one.
Author: Volodymyr Sapsai Date: 2023-02-22T11:01:40-08:00 New Revision: 2893d55f8f61edb2c253b960cab1107ea6c163c2 URL: https://github.com/llvm/llvm-project/commit/2893d55f8f61edb2c253b960cab1107ea6c163c2 DIFF: https://github.com/llvm/llvm-project/commit/2893d55f8f61edb2c253b960cab1107ea6c163c2.diff LOG: [Serialization] Don't warn when a deserialized category is equivalent to an existing one. A single class allows multiple categories to be defined for it. But if two of such categories have the same name, we emit a warning. It's not a hard error but a good indication of a potential mistake. With modules, we can end up with the same category in different modules. Diagnosing such a situation has little value as the categories in different modules are equivalent and don't reflect the usage of the same name for different purposes. When we deserialize a duplicate category, compare it to an existing one and warn only when the new one is different. rdar://104582081 Differential Revision: https://reviews.llvm.org/D144149 Added: Modified: clang/lib/Serialization/ASTReaderDecl.cpp clang/test/Modules/compare-objc-interface.m clang/test/Modules/hidden-duplicates.m clang/test/Modules/objc-categories.m Removed: diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 8cb513eff13e0..b9bbc0ec9eb28 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -14,6 +14,7 @@ #include "ASTCommon.h" #include "ASTReaderInternals.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/Attr.h" #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" @@ -4181,23 +4182,22 @@ namespace { // Check for duplicate categories. if (Cat->getDeclName()) { ObjCCategoryDecl * = NameCategoryMap[Cat->getDeclName()]; -if (Existing && -Reader.getOwningModuleFile(Existing) - != Reader.getOwningModuleFile(Cat)) { - // FIXME: We should not warn for duplicates in diamond: - // - // MT // - // / \// - // ML MR // - // \ /// - // MB // - // - // If there are duplicates in ML/MR, there will be warning when - // creating MB *and* when importing MB. We should not warn when - // importing. - Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) -<< Interface->getDeclName() << Cat->getDeclName(); - Reader.Diag(Existing->getLocation(), diag::note_previous_definition); +if (Existing && Reader.getOwningModuleFile(Existing) != +Reader.getOwningModuleFile(Cat)) { + llvm::DenseSet> NonEquivalentDecls; + StructuralEquivalenceContext Ctx( + Cat->getASTContext(), Existing->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, + /*StrictTypeSpelling =*/false, + /*Complain =*/false, + /*ErrorOnTagTypeMismatch =*/true); + if (!Ctx.IsEquivalent(Cat, Existing)) { +// Warn only if the categories with the same name are diff erent. +Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) +<< Interface->getDeclName() << Cat->getDeclName(); +Reader.Diag(Existing->getLocation(), +diag::note_previous_definition); + } } else if (!Existing) { // Record this category. Existing = Cat; diff --git a/clang/test/Modules/compare-objc-interface.m b/clang/test/Modules/compare-objc-interface.m index 17a03de3ce29b..cc3b5fe60b1f5 100644 --- a/clang/test/Modules/compare-objc-interface.m +++ b/clang/test/Modules/compare-objc-interface.m @@ -444,3 +444,54 @@ @interface CompareLastImplAttribute: NSObject // expected-error@first.h:* {{'CompareLastImplAttribute' has diff erent definitions in diff erent modules; first diff erence is definition in module 'First.Hidden' found property 'lastImplAttribute' with 'direct' attribute}} // expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'lastImplAttribute' with diff erent 'direct' attribute}} #endif + +#if defined(FIRST) +@interface CompareMatchingCategories: NSObject @end +@interface CompareMatchingCategories(Matching) +- (int)testMethod; +@end + +@interface CompareMismatchingCategories1: NSObject @end +@interface CompareMismatchingCategories1(Category1) +- (void)presentMethod; +@end +@interface CompareMismatchingCategories2: NSObject @end +@interface CompareMismatchingCategories2(Category2) +@end + +@interface CompareDifferentCategoryNames: NSObject @end +@interface CompareDifferentCategoryNames(CategoryFirst) +-
[clang] ed7a46a - [modules] Allow parsing a duplicate Obj-C interface if a previous one comes from a hidden [sub]module.
Author: Volodymyr Sapsai Date: 2023-01-20T10:18:18-06:00 New Revision: ed7a46a8de77087447936965044e2faf734102e5 URL: https://github.com/llvm/llvm-project/commit/ed7a46a8de77087447936965044e2faf734102e5 DIFF: https://github.com/llvm/llvm-project/commit/ed7a46a8de77087447936965044e2faf734102e5.diff LOG: [modules] Allow parsing a duplicate Obj-C interface if a previous one comes from a hidden [sub]module. Instead of emitting a redefinition error, check that definitions are equivalent and allow such scenario. A few non-obvious implementation details: * to avoid multiple definitions in the redeclaration chain we just drop the new definition after checking for equivalence; * for checking definition equivalence use ODR hash instead of ASTStructuralEquivalence because it avoids excessive recursive deserialization. Though after detecting a mismatch we do deserialize multiple entities to provide a better error message. rdar://82908223 Differential Revision: https://reviews.llvm.org/D124286 Added: Modified: clang/include/clang/AST/DeclObjC.h clang/include/clang/AST/ODRDiagsEmitter.h clang/include/clang/Basic/DiagnosticASTKinds.td clang/include/clang/Sema/Sema.h clang/lib/AST/DeclObjC.cpp clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/Parse/ParseObjc.cpp clang/lib/Sema/SemaDeclObjC.cpp clang/test/Modules/compare-objc-interface.m clang/test/Modules/hidden-duplicates.m Removed: diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 77fde99b6b60b..3d650b82f2b9b 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -1542,6 +1542,13 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// a forward declaration (\@class) to a definition (\@interface). void startDefinition(); + /// Starts the definition without sharing it with other redeclarations. + /// Such definition shouldn't be used for anything but only to compare if + /// a duplicate is compatible with previous definition or if it is + /// a distinct duplicate. + void startDuplicateDefinitionForComparison(); + void mergeDuplicateDefinitionWithCommon(const ObjCInterfaceDecl *Definition); + /// Retrieve the superclass type. const ObjCObjectType *getSuperClassType() const { if (TypeSourceInfo *TInfo = getSuperClassTInfo()) diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h index fdbd85cb10e5b..1f7faaa06e540 100644 --- a/clang/include/clang/AST/ODRDiagsEmitter.h +++ b/clang/include/clang/AST/ODRDiagsEmitter.h @@ -58,6 +58,15 @@ class ODRDiagsEmitter { const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID, const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const; + /// Diagnose ODR mismatch between ObjCInterfaceDecl with diff erent + /// definitions. + bool diagnoseMismatch(const ObjCInterfaceDecl *FirstID, +const ObjCInterfaceDecl *SecondID) const { +assert(FirstID->data().Definition != SecondID->data().Definition && + "Don't diagnose diff erences when definitions are merged already"); +return diagnoseMismatch(FirstID, SecondID, >data()); + } + /// Diagnose ODR mismatch between 2 ObjCProtocolDecl. /// /// Returns true if found a mismatch and diagnosed it. diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 715249b9d6f5e..28120d13fd9e7 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -624,12 +624,12 @@ def err_module_odr_violation_objc_interface : Error < "%select{|@private|@protected|@public|@package}5" "}3">; def note_module_odr_violation_objc_interface : Note < - "but in '%0' found " + "but in %select{'%1'|definition here}0 found " "%select{" - "%select{no super class|super class with type %3}2|" - "instance variable '%2' access control is " -"%select{|@private|@protected|@public|@package}3" - "}1">; + "%select{no super class|super class with type %4}3|" + "instance variable '%3' access control is " +"%select{|@private|@protected|@public|@package}4" + "}2">; def err_module_odr_violation_template_parameter : Error < "%q0 has diff erent definitions in diff erent modules; first diff erence is " @@ -778,16 +778,17 @@ def err_module_odr_violation_field : Error< "field %4 with %select{no|an}5 initalizer|" "field %4 with an initializer" "}3">; -def note_module_odr_violation_field : Note<"but in '%0' found " +def note_module_odr_violation_field : Note< + "but in %select{'%1'|definition here}0 found " "%select{" - "field %2|" - "field %2 with type %3|" - "%select{non-|}3bitfield %2|" - "bitfield %2 with diff erent width expression|" - "%select{non-|}3mutable field %2|" - "field %2 with
[clang] 6ba4afb - [ODRHash] Hash `ObjCInterfaceDecl` and diagnose discovered mismatches.
Author: Volodymyr Sapsai Date: 2023-01-20T10:18:18-06:00 New Revision: 6ba4afb4d6f2f8f293ad704a37de4139c5c8c0f0 URL: https://github.com/llvm/llvm-project/commit/6ba4afb4d6f2f8f293ad704a37de4139c5c8c0f0 DIFF: https://github.com/llvm/llvm-project/commit/6ba4afb4d6f2f8f293ad704a37de4139c5c8c0f0.diff LOG: [ODRHash] Hash `ObjCInterfaceDecl` and diagnose discovered mismatches. When two modules contain interfaces with the same name, check the definitions are equivalent and diagnose if they are not. Differential Revision: https://reviews.llvm.org/D140073 Added: clang/test/Modules/compare-objc-interface.m Modified: clang/include/clang/AST/DeclObjC.h clang/include/clang/AST/ODRDiagsEmitter.h clang/include/clang/AST/ODRHash.h clang/include/clang/Basic/DiagnosticASTKinds.td clang/include/clang/Serialization/ASTReader.h clang/lib/AST/DeclObjC.cpp clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/AST/ODRHash.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTReaderDecl.cpp clang/lib/Serialization/ASTWriter.cpp clang/lib/Serialization/ASTWriterDecl.cpp clang/test/Modules/interface-diagnose-missing-import.m clang/test/Modules/method_pool.m Removed: diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 7c72ec9507bf1..77fde99b6b60b 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -1146,6 +1146,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext { class ObjCInterfaceDecl : public ObjCContainerDecl , public Redeclarable { friend class ASTContext; + friend class ODRDiagsEmitter; /// TypeForDecl - This indicates the Type object that represents this /// TypeDecl. It is a cache maintained by ASTContext::getObjCInterfaceType @@ -1203,6 +1204,12 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// One of the \c InheritedDesignatedInitializersState enumeratos. mutable unsigned InheritedDesignatedInitializers : 2; +/// Tracks whether a ODR hash has been computed for this interface. +unsigned HasODRHash : 1; + +/// A hash of parts of the class to help in ODR checking. +unsigned ODRHash = 0; + /// The location of the last location in this declaration, before /// the properties/methods. For example, this will be the '>', '}', or /// identifier, @@ -1211,7 +1218,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl DefinitionData() : ExternallyCompleted(false), IvarListMissingImplementation(true), HasDesignatedInitializers(false), - InheritedDesignatedInitializers(IDI_Unknown) {} + InheritedDesignatedInitializers(IDI_Unknown), HasODRHash(false) {} }; /// The type parameters associated with this class, if any. @@ -1892,10 +1899,17 @@ class ObjCInterfaceDecl : public ObjCContainerDecl const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) const { TypeForDecl = TD; } + /// Get precomputed ODRHash or add a new one. + unsigned getODRHash(); + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCInterface; } private: + /// True if a valid hash is stored in ODRHash. + bool hasODRHash() const; + void setHasODRHash(bool HasHash); + const ObjCInterfaceDecl *findInterfaceWithDesignatedInitializers() const; bool inheritsDesignatedInitializers() const; }; diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h index 00a681b78a5eb..fdbd85cb10e5b 100644 --- a/clang/include/clang/AST/ODRDiagsEmitter.h +++ b/clang/include/clang/AST/ODRDiagsEmitter.h @@ -51,6 +51,13 @@ class ODRDiagsEmitter { bool diagnoseMismatch(const RecordDecl *FirstRecord, const RecordDecl *SecondRecord) const; + /// Diagnose ODR mismatch between 2 ObjCInterfaceDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch( + const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID, + const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const; + /// Diagnose ODR mismatch between 2 ObjCProtocolDecl. /// /// Returns true if found a mismatch and diagnosed it. @@ -97,6 +104,7 @@ class ODRDiagsEmitter { Friend, FunctionTemplate, ObjCMethod, +ObjCIvar, ObjCProperty, Other }; diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index a489bb73deb67..cedf644520fc3 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -59,6 +59,10 @@ class ODRHash { // method compares more information than the AddDecl class. void AddRecordDecl(const RecordDecl *Record); + // Use this for ODR checking ObjC interfaces.
[clang] f33b5b1 - [ODRHash] Detect mismatches in anonymous `RecordDecl`.
Author: Volodymyr Sapsai Date: 2023-01-19T15:58:31-06:00 New Revision: f33b5b1bf703ee5ff73126fefe2a9bcbd54db457 URL: https://github.com/llvm/llvm-project/commit/f33b5b1bf703ee5ff73126fefe2a9bcbd54db457 DIFF: https://github.com/llvm/llvm-project/commit/f33b5b1bf703ee5ff73126fefe2a9bcbd54db457.diff LOG: [ODRHash] Detect mismatches in anonymous `RecordDecl`. Allow completing a redeclaration check for anonymous structs/unions inside `RecordDecl`, so we deserialize and compare anonymous entities from different modules. Completing the redeclaration chain for `RecordDecl` in `ASTContext::getASTRecordLayout` mimics the behavior in `CXXRecordDecl::dataPtr`. Instead of completing the redeclaration chain every time we request a definition, do that right before we need a complete definition in `ASTContext::getASTRecordLayout`. Such code is required only for anonymous `RecordDecl` because we deserialize named decls when we look them up by name. But it doesn't work for anonymous decls as they don't have a name. That's why need to force deserialization of anonymous decls in a different way. rdar://81864186 Differential Revision: https://reviews.llvm.org/D140055 Added: Modified: clang/lib/AST/RecordLayoutBuilder.cpp clang/lib/Serialization/ASTReader.cpp clang/test/Modules/compare-record.c Removed: diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 52bd3f20221f4..da27f73ea94e2 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -3280,6 +3280,8 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { if (D->hasExternalLexicalStorage() && !D->getDefinition()) getExternalSource()->CompleteType(const_cast(D)); + // Complete the redecl chain (if necessary). + (void)D->getMostRecentDecl(); D = D->getDefinition(); assert(D && "Cannot get layout of forward declarations!"); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 77f29f6be4063..88d548a45b37d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7301,7 +7301,7 @@ void ASTReader::CompleteRedeclChain(const Decl *D) { // // FIXME: Merging a function definition should merge // all mergeable entities within it. - if (isa(DC)) { + if (isa(DC)) { if (DeclarationName Name = cast(D)->getDeclName()) { if (!getContext().getLangOpts().CPlusPlus && isa(DC)) { diff --git a/clang/test/Modules/compare-record.c b/clang/test/Modules/compare-record.c index 23dbe8191a343..a07843341296d 100644 --- a/clang/test/Modules/compare-record.c +++ b/clang/test/Modules/compare-record.c @@ -31,6 +31,15 @@ // REDEFINE: %{macro_flag} = -DCASE3=1 // RUN: %{command} +// Run tests for anonymous nested structs and unions +// REDEFINE: %{filename} = test-anonymous.c +// REDEFINE: %{macro_flag} = -DCASE1=1 +// RUN: %{command} +// REDEFINE: %{macro_flag} = -DCASE2=1 +// RUN: %{command} +// REDEFINE: %{macro_flag} = -DCASE3=1 +// RUN: %{command} + // Test that we don't accept diff erent structs and unions with the same name // from multiple modules but detect mismatches and provide actionable // diagnostic. @@ -44,12 +53,14 @@ module First { module Hidden { header "first.h" header "first-nested-struct.h" +header "first-anonymous.h" export * } } module Second { header "second.h" header "second-nested-struct.h" + header "second-anonymous.h" export * } @@ -416,3 +427,71 @@ struct CompareIndirectStructPointer compareIndirectStructPointer; // expected-error@second-nested-struct.h:* {{'IndirectStruct::mismatchingField' from module 'Second' is not present in definition of 'struct IndirectStruct' in module 'First.Hidden'}} // expected-note@first-nested-struct.h:* {{declaration of 'mismatchingField' does not match}} #endif + +//--- include/first-anonymous.h +struct CompareAnonymousNestedUnion { + union { +int anonymousNestedUnionField; + }; +}; + +struct CompareAnonymousNestedStruct { + struct { +int anonymousNestedStructField; + }; +}; + +struct CompareDeeplyNestedAnonymousUnionsAndStructs { + union { +int x; +union { + int y; + struct { +int z; + }; +}; + }; +}; + +//--- include/second-anonymous.h +struct CompareAnonymousNestedUnion { + union { +float anonymousNestedUnionField; + }; +}; + +struct CompareAnonymousNestedStruct { + struct { +float anonymousNestedStructField; + }; +}; + +struct CompareDeeplyNestedAnonymousUnionsAndStructs { + union { +int x; +union { + int y; + struct { +float z; + }; +}; + }; +}; + +//--- test-anonymous.c +#include "first-empty.h" +#include "second-anonymous.h" + +#if defined(CASE1) +struct CompareAnonymousNestedUnion compareAnonymousNestedUnion; +//
[clang] 160bc16 - [ODRHash] Hash `RecordDecl` and diagnose discovered mismatches.
Author: Volodymyr Sapsai Date: 2023-01-19T15:57:48-06:00 New Revision: 160bc160b9b114069a8cb9b4cc887aa86e5ca7c4 URL: https://github.com/llvm/llvm-project/commit/160bc160b9b114069a8cb9b4cc887aa86e5ca7c4 DIFF: https://github.com/llvm/llvm-project/commit/160bc160b9b114069a8cb9b4cc887aa86e5ca7c4.diff LOG: [ODRHash] Hash `RecordDecl` and diagnose discovered mismatches. When two modules contain struct/union with the same name, check the definitions are equivalent and diagnose if they are not. This is similar to `CXXRecordDecl` where we already discover and diagnose mismatches. rdar://problem/56764293 Differential Revision: https://reviews.llvm.org/D71734 Added: clang/test/Modules/compare-record.c Modified: clang/docs/ReleaseNotes.rst clang/include/clang/AST/Decl.h clang/include/clang/AST/DeclBase.h clang/include/clang/AST/ODRDiagsEmitter.h clang/include/clang/AST/ODRHash.h clang/include/clang/Serialization/ASTReader.h clang/lib/AST/Decl.cpp clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/AST/ODRHash.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTReaderDecl.cpp clang/lib/Serialization/ASTWriterDecl.cpp Removed: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 541f8e1eb671d..9f9fdc5a97a79 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -192,6 +192,10 @@ code bases. these definitions were allowed. Note that such definitions are ODR violations if the header is included more than once. +- Clang now diagnoses if structs/unions with the same name are diff erent in + diff erent used modules. Behavior in C and Objective-C language modes now is + the same as in C++. + What's New in Clang |release|? == Some of the major new features and improvements to Clang are listed diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 7322d4bcbc7f3..863f6ac57f2aa 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3998,6 +3998,7 @@ class RecordDecl : public TagDecl { // to save some space. Use the provided accessors to access it. public: friend class DeclContext; + friend class ASTDeclReader; /// Enum that represents the diff erent ways arguments are passed to and /// returned from function calls. This takes into account the target-specific /// and version-specific rules along with the rules determined by the @@ -4253,9 +4254,16 @@ class RecordDecl : public TagDecl { /// nullptr is returned if no named data member exists. const FieldDecl *findFirstNamedDataMember() const; + /// Get precomputed ODRHash or add a new one. + unsigned getODRHash(); + private: /// Deserialize just the fields. void LoadFieldsFromExternalStorage() const; + + /// True if a valid hash is stored in ODRHash. + bool hasODRHash() const { return RecordDeclBits.ODRHash; } + void setODRHash(unsigned Hash) { RecordDeclBits.ODRHash = Hash; } }; class FileScopeAsmDecl : public Decl { diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 8a5f75573095b..6134fdde8a2c9 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1577,10 +1577,14 @@ class DeclContext { /// Indicates whether this struct has had its field layout randomized. uint64_t IsRandomized : 1; + +/// True if a valid hash is stored in ODRHash. This should shave off some +/// extra storage and prevent CXXRecordDecl to store unused bits. +uint64_t ODRHash : 26; }; /// Number of non-inherited bits in RecordDeclBitfields. - enum { NumRecordDeclBits = 15 }; + enum { NumRecordDeclBits = 41 }; /// Stores the bits used by OMPDeclareReductionDecl. /// If modified NumOMPDeclareReductionDeclBits and the accessor diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h index d3b7f5e6b4109..00a681b78a5eb 100644 --- a/clang/include/clang/AST/ODRDiagsEmitter.h +++ b/clang/include/clang/AST/ODRDiagsEmitter.h @@ -45,6 +45,12 @@ class ODRDiagsEmitter { const CXXRecordDecl *SecondRecord, const struct CXXRecordDecl::DefinitionData *SecondDD) const; + /// Diagnose ODR mismatch between 2 RecordDecl that are not CXXRecordDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const RecordDecl *FirstRecord, +const RecordDecl *SecondRecord) const; + /// Diagnose ODR mismatch between 2 ObjCProtocolDecl. /// /// Returns true if found a mismatch and diagnosed it. diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index 1ab20013a3670..a489bb73deb67 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -55,6 +55,10 @@
[clang] 304d730 - [clang][Sema] Fix uninitialized `SourceLocation` for types with multiple attributes and macros.
Author: Volodymyr Sapsai Date: 2023-01-18T16:15:53-06:00 New Revision: 304d7307aee15b6eb88d198ae94b595f4e09f485 URL: https://github.com/llvm/llvm-project/commit/304d7307aee15b6eb88d198ae94b595f4e09f485 DIFF: https://github.com/llvm/llvm-project/commit/304d7307aee15b6eb88d198ae94b595f4e09f485.diff LOG: [clang][Sema] Fix uninitialized `SourceLocation` for types with multiple attributes and macros. Some `TypeLoc`s are considered "sugar" and we go past them in `GetTypeSourceInfoForDeclarator`. The problem is that we peel off only the same kind of `TypeLoc` at the time which makes it impossible to handle mixed sequences like `AttributedTypeLoc - MacroQualifiedTypeLoc - AttributedTypeLoc - PointerTypeLoc` In this situation, as shown in the added test, we don't get to `PointerTypeLoc` and don't set its starLoc leaving it uninitialized. Address FIXME and peel off "sugar" `TypeLoc`s regardless of their order. rdar://102149264 Differential Revision: https://reviews.llvm.org/D141424 Added: Modified: clang/lib/Sema/SemaType.cpp clang/unittests/AST/SourceLocationTest.cpp Removed: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index eb61a5fe4fbae..ac00e87944845 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6515,29 +6515,42 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState , CurrTL = ATL.getValueLoc().getUnqualifiedLoc(); } -while (MacroQualifiedTypeLoc TL = CurrTL.getAs()) { - TL.setExpansionLoc( - State.getExpansionLocForMacroQualifiedType(TL.getTypePtr())); - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); -} +bool HasDesugaredTypeLoc = true; +while (HasDesugaredTypeLoc) { + switch (CurrTL.getTypeLocClass()) { + case TypeLoc::MacroQualified: { +auto TL = CurrTL.castAs(); +TL.setExpansionLoc( +State.getExpansionLocForMacroQualifiedType(TL.getTypePtr())); +CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); +break; + } -while (AttributedTypeLoc TL = CurrTL.getAs()) { - fillAttributedTypeLoc(TL, State); - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); -} + case TypeLoc::Attributed: { +auto TL = CurrTL.castAs(); +fillAttributedTypeLoc(TL, State); +CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); +break; + } -while (BTFTagAttributedTypeLoc TL = CurrTL.getAs()) - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + case TypeLoc::Adjusted: + case TypeLoc::BTFTagAttributed: { +CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); +break; + } -while (DependentAddressSpaceTypeLoc TL = - CurrTL.getAs()) { - fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs()); - CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc(); -} + case TypeLoc::DependentAddressSpace: { +auto TL = CurrTL.castAs(); +fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs()); +CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc(); +break; + } -// FIXME: Ordering here? -while (AdjustedTypeLoc TL = CurrTL.getAs()) - CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + default: +HasDesugaredTypeLoc = false; +break; + } +} DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); diff --git a/clang/unittests/AST/SourceLocationTest.cpp b/clang/unittests/AST/SourceLocationTest.cpp index 43b7149bd1183..ca9e9a2161974 100644 --- a/clang/unittests/AST/SourceLocationTest.cpp +++ b/clang/unittests/AST/SourceLocationTest.cpp @@ -438,6 +438,47 @@ TEST(UnaryTransformTypeLoc, ParensRange) { loc(unaryTransformType(; } +TEST(PointerTypeLoc, StarLoc) { + llvm::Annotations Example(R"c( +int $star^*var; + )c"); + + auto AST = tooling::buildASTFromCode(Example.code()); + SourceManager = AST->getSourceManager(); + auto = AST->getASTContext(); + + auto *VD = selectFirst("vd", match(varDecl(hasName("var")).bind("vd"), Ctx)); + ASSERT_NE(VD, nullptr); + + auto TL = + VD->getTypeSourceInfo()->getTypeLoc().castAs(); + ASSERT_EQ(SM.getFileOffset(TL.getStarLoc()), Example.point("star")); +} + +TEST(PointerTypeLoc, StarLocBehindSugar) { + llvm::Annotations Example(R"c( +#define NODEREF __attribute__((noderef)) +char $1st^* NODEREF _Nonnull $2nd^* var; + )c"); + + auto AST = tooling::buildASTFromCode(Example.code()); + SourceManager = AST->getSourceManager(); + auto = AST->getASTContext(); + + auto *VD = selectFirst("vd", match(varDecl(hasName("var")).bind("vd"), Ctx)); + ASSERT_NE(VD, nullptr); + + auto TL = VD->getTypeSourceInfo()->getTypeLoc().castAs(); + EXPECT_EQ(SM.getFileOffset(TL.getStarLoc()), Example.point("2nd"));
[clang] 574a77a - [clang][sema][Matrix] Move code from try-cast to `TypeLocVisitor`. NFC intended.
Author: Volodymyr Sapsai Date: 2023-01-17T15:33:36-06:00 New Revision: 574a77ae85451adc5e2dd9e73652c62bf18eed8d URL: https://github.com/llvm/llvm-project/commit/574a77ae85451adc5e2dd9e73652c62bf18eed8d DIFF: https://github.com/llvm/llvm-project/commit/574a77ae85451adc5e2dd9e73652c62bf18eed8d.diff LOG: [clang][sema][Matrix] Move code from try-cast to `TypeLocVisitor`. NFC intended. `MatrixTypeLoc` is not "sugar" `TypeLoc` and doesn't require to use the underlying `TypeLoc` instead. Differential Revision: https://reviews.llvm.org/D141422 Added: Modified: clang/lib/Sema/SemaType.cpp Removed: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 826a9ef954ee..eb61a5fe4fba 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6053,6 +6053,21 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL, TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr())); } +static void fillMatrixTypeLoc(MatrixTypeLoc MTL, + const ParsedAttributesView ) { + for (const ParsedAttr : Attrs) { +if (AL.getKind() == ParsedAttr::AT_MatrixType) { + MTL.setAttrNameLoc(AL.getLoc()); + MTL.setAttrRowOperand(AL.getArgAsExpr(0)); + MTL.setAttrColumnOperand(AL.getArgAsExpr(1)); + MTL.setAttrOperandParensRange(SourceRange()); + return; +} + } + + llvm_unreachable("no matrix_type attribute found at the expected location!"); +} + namespace { class TypeSpecLocFiller : public TypeLocVisitor { Sema @@ -6419,6 +6434,9 @@ namespace { VisitDependentSizedExtVectorTypeLoc(DependentSizedExtVectorTypeLoc TL) { TL.setNameLoc(Chunk.Loc); } +void VisitMatrixTypeLoc(MatrixTypeLoc TL) { + fillMatrixTypeLoc(TL, Chunk.getAttrs()); +} void VisitTypeLoc(TypeLoc TL) { llvm_unreachable("unsupported TypeLoc kind in declarator!"); @@ -6466,21 +6484,6 @@ fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, "no address_space attribute found at the expected location!"); } -static void fillMatrixTypeLoc(MatrixTypeLoc MTL, - const ParsedAttributesView ) { - for (const ParsedAttr : Attrs) { -if (AL.getKind() == ParsedAttr::AT_MatrixType) { - MTL.setAttrNameLoc(AL.getLoc()); - MTL.setAttrRowOperand(AL.getArgAsExpr(0)); - MTL.setAttrColumnOperand(AL.getArgAsExpr(1)); - MTL.setAttrOperandParensRange(SourceRange()); - return; -} - } - - llvm_unreachable("no matrix_type attribute found at the expected location!"); -} - /// Create and instantiate a TypeSourceInfo with type source information. /// /// \param T QualType referring to the type as written in source code. @@ -6532,9 +6535,6 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState , CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc(); } -if (MatrixTypeLoc TL = CurrTL.getAs()) - fillMatrixTypeLoc(TL, D.getTypeObject(i).getAttrs()); - // FIXME: Ordering here? while (AdjustedTypeLoc TL = CurrTL.getAs()) CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 642c663 - Reland "[clang][deps] During scanning don't emit warnings-as-errors that are ignored with diagnostic pragmas."
Author: Volodymyr Sapsai Date: 2022-12-02T14:30:41-08:00 New Revision: 642c6638a3d78359552f5cf71d24a80a9bd9801f URL: https://github.com/llvm/llvm-project/commit/642c6638a3d78359552f5cf71d24a80a9bd9801f DIFF: https://github.com/llvm/llvm-project/commit/642c6638a3d78359552f5cf71d24a80a9bd9801f.diff LOG: Reland "[clang][deps] During scanning don't emit warnings-as-errors that are ignored with diagnostic pragmas." This reverts commit 2f8ac1804827026b44f429dce02730da18a73c50. After committing a fix for previous buildbot failures in D138970, re-landing the original change. Added: clang/test/ClangScanDeps/diagnostic-pragmas.c Modified: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp Removed: diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 50c42087d2fa2..ff2d4b76820ed 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -135,8 +135,8 @@ static void sanitizeDiagOpts(DiagnosticOptions ) { DiagOpts.ShowCarets = false; // Don't write out diagnostic file. DiagOpts.DiagnosticSerializationFile.clear(); - // Don't treat warnings as errors. - DiagOpts.Warnings.push_back("no-error"); + // Don't emit warnings as errors (and all other warnings too). + DiagOpts.IgnoreWarnings = true; } /// A clang tool that runs the preprocessor in a mode that's optimized for diff --git a/clang/test/ClangScanDeps/diagnostic-pragmas.c b/clang/test/ClangScanDeps/diagnostic-pragmas.c new file mode 100644 index 0..520f82047d2b1 --- /dev/null +++ b/clang/test/ClangScanDeps/diagnostic-pragmas.c @@ -0,0 +1,35 @@ +// Test scanning deps does not have more errors than the regular compilation. + +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json + +// Check the regular compilation does not fail. +// RUN: %clang -fsyntax-only %t/test.c -I %t/include -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -Wnon-modular-include-in-module -Werror=non-modular-include-in-module + +// And now scanning deps should succeed too. +// RUN: clang-scan-deps -compilation-database %t/cdb.json -j 1 + +//--- cdb.json.template +[ + { +"directory": "DIR", +"command": "clang -fsyntax-only DIR/test.c -I DIR/include -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -Wnon-modular-include-in-module -Werror=non-modular-include-in-module", +"file": "DIR/test.c" + }, +] + +//--- include/nonmodular.h +// empty + +//--- include/modular-includer.h +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnon-modular-include-in-module" +#include +#pragma clang diagnostic pop + +//--- include/module.modulemap +module ModularIncluder { header "modular-includer.h" } + +//--- test.c +#include ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] b4b5469 - [clang][Driver] Don't overwrite `DiagnosticsEngine::IgnoreAllWarnings`, rely on `DiagnosticOptions::IgnoreWarnings` value.
Author: Volodymyr Sapsai Date: 2022-12-02T11:59:22-08:00 New Revision: b4b54697b7aacda1fabef36d4e74d5ee45641618 URL: https://github.com/llvm/llvm-project/commit/b4b54697b7aacda1fabef36d4e74d5ee45641618 DIFF: https://github.com/llvm/llvm-project/commit/b4b54697b7aacda1fabef36d4e74d5ee45641618.diff LOG: [clang][Driver] Don't overwrite `DiagnosticsEngine::IgnoreAllWarnings`, rely on `DiagnosticOptions::IgnoreWarnings` value. Driver overwrites `DiagnosticsEngine::IgnoreAllWarnings` based on `-w` flag without taking into account `DiagnosticOptions::IgnoreWarnings` that is propagated to `DiagnosticsEngine` in `ProcessWarningOptions` (called from `CompilerInstance::createDiagnostics`). It makes it hard to manipulate `DiagnosticOptions` directly and pushes towards string-based API. Most of in-tree tools use `DiagnosticOptions` already, so migrate `clang_parseTranslationUnit_Impl` to use it too. Don't parse `-w` directly but rely on ``` def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>, MarshallingInfoFlag>; ``` Allows to reland D138252. Differential Revision: https://reviews.llvm.org/D138970 Added: Modified: clang/lib/Driver/Driver.cpp clang/tools/libclang/CIndex.cpp Removed: diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 5423fdc9855eb..6bd2d38f65744 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1211,9 +1211,6 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { // FIXME: This stuff needs to go into the Compilation, not the driver. bool CCCPrintPhases; - // Silence driver warnings if requested - Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w)); - // -canonical-prefixes, -no-canonical-prefixes are used very early in main. Args.ClaimAllArgs(options::OPT_canonical_prefixes); Args.ClaimAllArgs(options::OPT_no_canonical_prefixes); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index dec7efd7bfb14..4210f162569ed 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -3797,8 +3797,10 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename, } // Configure the diagnostics. + std::unique_ptr DiagOpts = CreateAndPopulateDiagOpts( + llvm::makeArrayRef(command_line_args, num_command_line_args)); IntrusiveRefCntPtr Diags( - CompilerInstance::createDiagnostics(new DiagnosticOptions)); + CompilerInstance::createDiagnostics(DiagOpts.release())); if (options & CXTranslationUnit_KeepGoing) Diags->setFatalsAsError(true); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] eac90d1 - [clang][deps] During scanning don't emit warnings-as-errors that are ignored with diagnostic pragmas.
Author: Volodymyr Sapsai Date: 2022-11-28T13:48:29-08:00 New Revision: eac90d1236cfd2935fac5cbe5634f09e2cd0981a URL: https://github.com/llvm/llvm-project/commit/eac90d1236cfd2935fac5cbe5634f09e2cd0981a DIFF: https://github.com/llvm/llvm-project/commit/eac90d1236cfd2935fac5cbe5634f09e2cd0981a.diff LOG: [clang][deps] During scanning don't emit warnings-as-errors that are ignored with diagnostic pragmas. Before the fix the scanning would fail with `-Werror,-Wnon-modular-include-in-module` despite the warning being suppressed in the source code. Existing approach with `-Wno-error` is not sufficient because it negates only general `-Werror` but not specific `-Werror=...` and some warnings can still emitted as errors. Make the approach stricter by using `-w` flag and ignore all warnings, including those upgraded to errors. This approach is still valid as it doesn't affect the dependencies. rdar://101588531 Differential Revision: https://reviews.llvm.org/D138252 Added: clang/test/ClangScanDeps/diagnostic-pragmas.c Modified: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp Removed: diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 50c42087d2fa..ff2d4b76820e 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -135,8 +135,8 @@ static void sanitizeDiagOpts(DiagnosticOptions ) { DiagOpts.ShowCarets = false; // Don't write out diagnostic file. DiagOpts.DiagnosticSerializationFile.clear(); - // Don't treat warnings as errors. - DiagOpts.Warnings.push_back("no-error"); + // Don't emit warnings as errors (and all other warnings too). + DiagOpts.IgnoreWarnings = true; } /// A clang tool that runs the preprocessor in a mode that's optimized for diff --git a/clang/test/ClangScanDeps/diagnostic-pragmas.c b/clang/test/ClangScanDeps/diagnostic-pragmas.c new file mode 100644 index ..520f82047d2b --- /dev/null +++ b/clang/test/ClangScanDeps/diagnostic-pragmas.c @@ -0,0 +1,35 @@ +// Test scanning deps does not have more errors than the regular compilation. + +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json + +// Check the regular compilation does not fail. +// RUN: %clang -fsyntax-only %t/test.c -I %t/include -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -Wnon-modular-include-in-module -Werror=non-modular-include-in-module + +// And now scanning deps should succeed too. +// RUN: clang-scan-deps -compilation-database %t/cdb.json -j 1 + +//--- cdb.json.template +[ + { +"directory": "DIR", +"command": "clang -fsyntax-only DIR/test.c -I DIR/include -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -Wnon-modular-include-in-module -Werror=non-modular-include-in-module", +"file": "DIR/test.c" + }, +] + +//--- include/nonmodular.h +// empty + +//--- include/modular-includer.h +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnon-modular-include-in-module" +#include +#pragma clang diagnostic pop + +//--- include/module.modulemap +module ModularIncluder { header "modular-includer.h" } + +//--- test.c +#include ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 0314ba3 - [modules] Fix marking `ObjCMethodDecl::isOverriding` when there are no overrides.
Author: Volodymyr Sapsai Date: 2022-11-24T14:26:02-08:00 New Revision: 0314ba3acbabd8dc6d39b6d49798d22b6dc33802 URL: https://github.com/llvm/llvm-project/commit/0314ba3acbabd8dc6d39b6d49798d22b6dc33802 DIFF: https://github.com/llvm/llvm-project/commit/0314ba3acbabd8dc6d39b6d49798d22b6dc33802.diff LOG: [modules] Fix marking `ObjCMethodDecl::isOverriding` when there are no overrides. Incorrect `isOverriding` flag triggers the assertion `!Overridden.empty()` in `ObjCMethodDecl::getOverriddenMethods` when a method is marked as overriding but we cannot find any overrides. When a method is declared in a category and defined in implementation, we don't treat it as an override because it is the same method with a separate declaration and a definition. But with modules we can find a method declaration both in a modular category and a non-modular category with different memory addresses. Thus we erroneously conclude the method is overriding. Fix by comparing canonical declarations that are the same for equal entities coming from different modules. rdar://92845511 Differential Revision: https://reviews.llvm.org/D138630 Added: clang/test/Modules/override.m Modified: clang/lib/Sema/SemaDeclObjC.cpp Removed: diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 97dff49862bb5..0cd764552b932 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -4438,6 +4438,11 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, ResultTypeCompatibilityKind RTC) { if (!ObjCMethod) return; + auto IsMethodInCurrentClass = [CurrentClass](const ObjCMethodDecl *M) { +// Checking canonical decl works across modules. +return M->getClassInterface()->getCanonicalDecl() == + CurrentClass->getCanonicalDecl(); + }; // Search for overridden methods and merge information down from them. OverrideSearch overrides(*this, ObjCMethod); // Keep track if the method overrides any method in the class's base classes, @@ -4449,8 +4454,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, for (ObjCMethodDecl *overridden : overrides) { if (!hasOverriddenMethodsInBaseOrProtocol) { if (isa(overridden->getDeclContext()) || - CurrentClass != overridden->getClassInterface() || - overridden->isOverriding()) { + !IsMethodInCurrentClass(overridden) || overridden->isOverriding()) { CheckObjCMethodDirectOverrides(ObjCMethod, overridden); hasOverriddenMethodsInBaseOrProtocol = true; } else if (isa(ObjCMethod->getDeclContext())) { @@ -4475,7 +4479,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, OverrideSearch overrides(*this, overridden); for (ObjCMethodDecl *SuperOverridden : overrides) { if (isa(SuperOverridden->getDeclContext()) || -CurrentClass != SuperOverridden->getClassInterface()) { +!IsMethodInCurrentClass(SuperOverridden)) { CheckObjCMethodDirectOverrides(ObjCMethod, SuperOverridden); hasOverriddenMethodsInBaseOrProtocol = true; overridden->setOverriding(true); diff --git a/clang/test/Modules/override.m b/clang/test/Modules/override.m new file mode 100644 index 0..247c2be76ee14 --- /dev/null +++ b/clang/test/Modules/override.m @@ -0,0 +1,69 @@ +// UNSUPPORTED: -aix +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -fsyntax-only -I%t/include %t/test.m \ +// RUN:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache -fmodule-name=CheckOverride + +// Test that if we have the same method in a diff erent module, it's not an +// override as it is the same method and it has the same DeclContext but a +// diff erent object in the memory. + + +//--- include/CheckOverride.h +@interface NSObject +@end + +@interface CheckOverrideInterfaceOnly: NSObject +- (void)potentialOverrideInterfaceOnly; +@end + +@interface CheckOverrideCategoryOnly: NSObject +@end +@interface CheckOverrideCategoryOnly(CategoryOnly) +- (void)potentialOverrideCategoryOnly; +@end + +@interface CheckOverrideImplementationOfInterface: NSObject +- (void)potentialOverrideImplementationOfInterface; +@end + +@interface CheckOverrideImplementationOfCategory: NSObject +@end +@interface CheckOverrideImplementationOfCategory(CategoryImpl) +- (void)potentialOverrideImplementationOfCategory; +@end + +//--- include/Redirect.h +// Ensure CheckOverride is imported as the module despite all `-fmodule-name` flags. +#import + +//--- include/module.modulemap +module CheckOverride { + header "CheckOverride.h" +} +module Redirect { + header "Redirect.h" + export * +} + +//--- test.m +#import +#import + +@implementation CheckOverrideImplementationOfInterface
[clang] a65d530 - [ODRHash] Detect duplicate `ObjCProtocolDecl` ODR mismatches during parsing.
Author: Volodymyr Sapsai Date: 2022-11-17T18:31:32-08:00 New Revision: a65d5309d5b73527efcbdec49a3ba9bba0fd873d URL: https://github.com/llvm/llvm-project/commit/a65d5309d5b73527efcbdec49a3ba9bba0fd873d DIFF: https://github.com/llvm/llvm-project/commit/a65d5309d5b73527efcbdec49a3ba9bba0fd873d.diff LOG: [ODRHash] Detect duplicate `ObjCProtocolDecl` ODR mismatches during parsing. When during parsing we encountered a duplicate `ObjCProtocolDecl`, we were always emitting an error. With this change we accept * when a previous `ObjCProtocolDecl` is in a hidden [sub]module; * parsed `ObjCProtocolDecl` is the same as the previous one. And in case of mismatches we provide more detailed error messages. rdar://93069080 Differential Revision: https://reviews.llvm.org/D130327 Added: clang/test/Modules/hidden-duplicates.m Modified: clang/include/clang/AST/DeclObjC.h clang/include/clang/AST/ODRDiagsEmitter.h clang/include/clang/Basic/DiagnosticASTKinds.td clang/include/clang/Sema/Sema.h clang/lib/AST/DeclObjC.cpp clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/Parse/ParseObjc.cpp clang/lib/Sema/SemaDeclObjC.cpp clang/test/Modules/compare-objc-protocol.m Removed: diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 3d20d172dc631..6e83060d5a4d4 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -2230,6 +2230,13 @@ class ObjCProtocolDecl : public ObjCContainerDecl, /// Starts the definition of this Objective-C protocol. void startDefinition(); + /// Starts the definition without sharing it with other redeclarations. + /// Such definition shouldn't be used for anything but only to compare if + /// a duplicate is compatible with previous definition or if it is + /// a distinct duplicate. + void startDuplicateDefinitionForComparison(); + void mergeDuplicateDefinitionWithCommon(const ObjCProtocolDecl *Definition); + /// Produce a name to be used for protocol's metadata. It comes either via /// objc_runtime_name attribute or protocol name. StringRef getObjCRuntimeNameAsString() const; diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h index 4c41a4a6004f1..d3b7f5e6b4109 100644 --- a/clang/include/clang/AST/ODRDiagsEmitter.h +++ b/clang/include/clang/AST/ODRDiagsEmitter.h @@ -55,6 +55,16 @@ class ODRDiagsEmitter { const ObjCProtocolDecl *SecondProtocol, const struct ObjCProtocolDecl::DefinitionData *SecondDD) const; + /// Diagnose ODR mismatch between ObjCProtocolDecl with diff erent definitions. + bool diagnoseMismatch(const ObjCProtocolDecl *FirstProtocol, +const ObjCProtocolDecl *SecondProtocol) const { +assert(FirstProtocol->data().Definition != + SecondProtocol->data().Definition && + "Don't diagnose diff erences when definitions are merged already"); +return diagnoseMismatch(FirstProtocol, SecondProtocol, +>data()); + } + /// Get the best name we know for the module that owns the given /// declaration, or an empty string if the declaration is not from a module. static std::string getOwningModuleNameForDiagnostic(const Decl *D); diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 0f7e256d8056f..15bd9d7c0e49a 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -622,10 +622,11 @@ def err_module_odr_violation_mismatch_decl : Error< "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" "data member|friend declaration|function template|method|property}3">; -def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " +def note_module_odr_violation_mismatch_decl : Note< + "but in %select{'%1'|definition here}0 found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration|function template|method|property}1">; + "data member|friend declaration|function template|method|property}2">; def err_module_odr_violation_record : Error< "%q0 has diff erent definitions in diff erent modules; first diff erence is " @@ -843,11 +844,12 @@ def err_module_odr_violation_referenced_protocols : Error < "%4 referenced %plural{1:protocol|:protocols}4|" "%ordinal4 referenced protocol with name %5" "}3">; -def note_module_odr_violation_referenced_protocols : Note <"but in '%0' found " +def note_module_odr_violation_referenced_protocols : Note < + "but in %select{'%1'|definition here}0 found " "%select{" - "%2 referenced
[clang] dcb71b5 - [ODRHash] Hash `ObjCPropertyDecl` and diagnose discovered mismatches.
Author: Volodymyr Sapsai Date: 2022-11-17T17:22:03-08:00 New Revision: dcb71b5e1d1311c41f409c8dab26e04b084875be URL: https://github.com/llvm/llvm-project/commit/dcb71b5e1d1311c41f409c8dab26e04b084875be DIFF: https://github.com/llvm/llvm-project/commit/dcb71b5e1d1311c41f409c8dab26e04b084875be.diff LOG: [ODRHash] Hash `ObjCPropertyDecl` and diagnose discovered mismatches. Differential Revision: https://reviews.llvm.org/D130326 Added: Modified: clang/include/clang/AST/ODRDiagsEmitter.h clang/include/clang/Basic/DiagnosticASTKinds.td clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/AST/ODRHash.cpp clang/test/Modules/compare-objc-protocol.m Removed: diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h index cbabaa7e69b41..4c41a4a6004f1 100644 --- a/clang/include/clang/AST/ODRDiagsEmitter.h +++ b/clang/include/clang/AST/ODRDiagsEmitter.h @@ -81,6 +81,7 @@ class ODRDiagsEmitter { Friend, FunctionTemplate, ObjCMethod, +ObjCProperty, Other }; @@ -149,6 +150,15 @@ class ODRDiagsEmitter { const ObjCMethodDecl *FirstMethod, const ObjCMethodDecl *SecondMethod) const; + /// Check if Objective-C properties are the same and diagnose if diff erent. + /// + /// Returns true if found a mismatch and diagnosed it. + bool + diagnoseSubMismatchObjCProperty(const NamedDecl *FirstObjCContainer, + StringRef FirstModule, StringRef SecondModule, + const ObjCPropertyDecl *FirstProp, + const ObjCPropertyDecl *SecondProp) const; + private: DiagnosticsEngine const ASTContext diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index af7aec65bf6c8..0f7e256d8056f 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -621,11 +621,11 @@ def err_module_odr_violation_mismatch_decl : Error< "%select{definition in module '%2'|defined here}1 found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration|function template|method}3">; + "data member|friend declaration|function template|method|property}3">; def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration|function template|method}1">; + "data member|friend declaration|function template|method|property}1">; def err_module_odr_violation_record : Error< "%q0 has diff erent definitions in diff erent modules; first diff erence is " @@ -891,18 +891,40 @@ def note_module_odr_violation_method_params : Note<"but in '%0' found " "with %ordinal4 parameter named %5" "}1">; +def err_module_odr_violation_objc_property : Error< + "%q0 has diff erent definitions in diff erent modules; first diff erence is " + "%select{definition in module '%2'|defined here}1 found " + "%select{" + "property %4|" + "property %4 with type %5|" + "%select{no|'required'|'optional'}4 property control|" + "property %4 with %select{default |}6'%select{none|readonly|getter|assign|" +"readwrite|retain|copy|nonatomic|setter|atomic|weak|strong|" +"unsafe_unretained|nullability|null_resettable|class|direct}5' attribute" + "}3">; +def note_module_odr_violation_objc_property : Note< + "but in '%0' found " + "%select{" + "property %2|" + "property %2 with type %3|" + "%select{no|'required'|'optional'}2 property control|" + "property %2 with diff erent '%select{none|readonly|getter|assign|" +"readwrite|retain|copy|nonatomic|setter|atomic|weak|strong|" +"unsafe_unretained|nullability|null_resettable|class|direct}3' attribute" + "}1">; + def err_module_odr_violation_mismatch_decl_unknown : Error< "%q0 %select{with definition in module '%2'|defined here}1 has diff erent " "definitions in diff erent modules; first diff erence is this " "%select{static assert|field|method|type alias|typedef|data member|" "friend declaration|function template|method|" - "unexpected decl}3">; + "property|unexpected decl}3">; def note_module_odr_violation_mismatch_decl_unknown : Note< "but in '%0' found " "%select{ diff erent static assert| diff erent field| diff erent method|" " diff erent type alias| diff erent typedef| diff erent data member|" " diff erent friend declaration| diff erent function template| diff erent method|" - "another unexpected decl}1">; + " diff erent property|another unexpected decl}1">; def
[clang] 2662009 - [ODRHash] Hash `ObjCMethodDecl` and diagnose discovered mismatches.
Author: Volodymyr Sapsai Date: 2022-10-17T18:48:24-07:00 New Revision: 2662009c87f470ec5bc13c237cd62c57b28e4032 URL: https://github.com/llvm/llvm-project/commit/2662009c87f470ec5bc13c237cd62c57b28e4032 DIFF: https://github.com/llvm/llvm-project/commit/2662009c87f470ec5bc13c237cd62c57b28e4032.diff LOG: [ODRHash] Hash `ObjCMethodDecl` and diagnose discovered mismatches. Differential Revision: https://reviews.llvm.org/D130325 Added: Modified: clang/include/clang/AST/ODRDiagsEmitter.h clang/include/clang/Basic/DiagnosticASTKinds.td clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/AST/ODRHash.cpp clang/test/Modules/compare-objc-protocol.m Removed: diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h index d79b3e1c0649..cbabaa7e69b4 100644 --- a/clang/include/clang/AST/ODRDiagsEmitter.h +++ b/clang/include/clang/AST/ODRDiagsEmitter.h @@ -62,8 +62,10 @@ class ODRDiagsEmitter { private: using DeclHashes = llvm::SmallVector, 4>; - // Used with err_module_odr_violation_mismatch_decl and - // note_module_odr_violation_mismatch_decl + // Used with err_module_odr_violation_mismatch_decl, + // note_module_odr_violation_mismatch_decl, + // err_module_odr_violation_mismatch_decl_unknown, + // and note_module_odr_violation_mismatch_decl_unknown // This list should be the same Decl's as in ODRHash::isSubDeclToBeProcessed enum ODRMismatchDecl { EndOfClass, @@ -78,6 +80,7 @@ class ODRDiagsEmitter { Var, Friend, FunctionTemplate, +ObjCMethod, Other }; @@ -137,6 +140,15 @@ class ODRDiagsEmitter { const ObjCContainerDecl *SecondContainer, StringRef SecondModule) const; + /// Check if Objective-C methods are the same and diagnose if diff erent. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseSubMismatchObjCMethod(const NamedDecl *FirstObjCContainer, + StringRef FirstModule, + StringRef SecondModule, + const ObjCMethodDecl *FirstMethod, + const ObjCMethodDecl *SecondMethod) const; + private: DiagnosticsEngine const ASTContext diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 2517f52a7cf7..c4f520442549 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -621,11 +621,11 @@ def err_module_odr_violation_mismatch_decl : Error< "%select{definition in module '%2'|defined here}1 found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration|function template}3">; + "data member|friend declaration|function template|method}3">; def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration|function template}1">; + "data member|friend declaration|function template|method}1">; def err_module_odr_violation_record : Error< "%q0 has diff erent definitions in diff erent modules; first diff erence is " @@ -649,12 +649,6 @@ def err_module_odr_violation_record : Error< "is %select{not const|const}6|" "%select{method %5|constructor|destructor}4 " "is %select{not inline|inline}6|" - "%select{method %5|constructor|destructor}4 " -"that has %6 parameter%s6|" - "%select{method %5|constructor|destructor}4 " -"with %ordinal6 parameter of type %7%select{| decayed from %9}8|" - "%select{method %5|constructor|destructor}4 " -"with %ordinal6 parameter named %7|" "%select{method %5|constructor|destructor}4 " "with %ordinal6 parameter with%select{out|}7 a default argument|" "%select{method %5|constructor|destructor}4 " @@ -706,12 +700,6 @@ def note_module_odr_violation_record : Note<"but in '%0' found " "is %select{not const|const}4|" "%select{method %3|constructor|destructor}2 " "is %select{not inline|inline}4|" - "%select{method %3|constructor|destructor}2 " -"that has %4 parameter%s4|" - "%select{method %3|constructor|destructor}2 " -"with %ordinal4 parameter of type %5%select{| decayed from %7}6|" - "%select{method %3|constructor|destructor}2 " -"with %ordinal4 parameter named %5|" "%select{method %3|constructor|destructor}2 " "with %ordinal4 parameter with%select{out|}5 a default argument|" "%select{method %3|constructor|destructor}2 " @@ -861,17 +849,59 @@ def note_module_odr_violation_referenced_protocols : Note <"but in '%0'
[clang] 37fdca2 - [ODRHash] Rename `isDeclToBeProcessed` to `isSubDeclToBeProcessed`. NFC intended.
Author: Volodymyr Sapsai Date: 2022-10-17T18:24:44-07:00 New Revision: 37fdca21f7f61dee5426f55b0ee7bf601d95afcd URL: https://github.com/llvm/llvm-project/commit/37fdca21f7f61dee5426f55b0ee7bf601d95afcd DIFF: https://github.com/llvm/llvm-project/commit/37fdca21f7f61dee5426f55b0ee7bf601d95afcd.diff LOG: [ODRHash] Rename `isDeclToBeProcessed` to `isSubDeclToBeProcessed`. NFC intended. The method is used only for sub-Decls, so reflect that in the name. Added: Modified: clang/include/clang/AST/ODRDiagsEmitter.h clang/include/clang/AST/ODRHash.h clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/AST/ODRHash.cpp Removed: diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h index af345310c3a4..d79b3e1c0649 100644 --- a/clang/include/clang/AST/ODRDiagsEmitter.h +++ b/clang/include/clang/AST/ODRDiagsEmitter.h @@ -64,7 +64,7 @@ class ODRDiagsEmitter { // Used with err_module_odr_violation_mismatch_decl and // note_module_odr_violation_mismatch_decl - // This list should be the same Decl's as in ODRHash::isDeclToBeProcessed + // This list should be the same Decl's as in ODRHash::isSubDeclToBeProcessed enum ODRMismatchDecl { EndOfClass, PublicSpecifer, diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index 59b74cf477dd..1ab20013a367 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -93,7 +93,7 @@ class ODRHash { // Save booleans until the end to lower the size of data to process. void AddBoolean(bool value); - static bool isDeclToBeProcessed(const Decl* D, const DeclContext *Parent); + static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent); private: void AddDeclarationNameImpl(DeclarationName Name); diff --git a/clang/lib/AST/ODRDiagsEmitter.cpp b/clang/lib/AST/ODRDiagsEmitter.cpp index 3cc280a53a8c..1fda502e323b 100644 --- a/clang/lib/AST/ODRDiagsEmitter.cpp +++ b/clang/lib/AST/ODRDiagsEmitter.cpp @@ -630,7 +630,7 @@ bool ODRDiagsEmitter::diagnoseMismatch( auto PopulateHashes = [](DeclHashes , const RecordDecl *Record, const DeclContext *DC) { for (const Decl *D : Record->decls()) { - if (!ODRHash::isDeclToBeProcessed(D, DC)) + if (!ODRHash::isSubDeclToBeProcessed(D, DC)) continue; Hashes.emplace_back(D, computeODRHash(D)); } @@ -1538,7 +1538,7 @@ bool ODRDiagsEmitter::diagnoseMismatch(const EnumDecl *FirstEnum, for (const Decl *D : Enum->decls()) { // Due to decl merging, the first EnumDecl is the parent of // Decls in both records. - if (!ODRHash::isDeclToBeProcessed(D, FirstEnum)) + if (!ODRHash::isSubDeclToBeProcessed(D, FirstEnum)) continue; assert(isa(D) && "Unexpected Decl kind"); Hashes.emplace_back(cast(D), computeODRHash(D)); @@ -1620,7 +1620,7 @@ bool ODRDiagsEmitter::diagnoseMismatch( auto PopulateHashes = [](DeclHashes , const ObjCProtocolDecl *ID, const DeclContext *DC) { for (const Decl *D : ID->decls()) { - if (!ODRHash::isDeclToBeProcessed(D, DC)) + if (!ODRHash::isSubDeclToBeProcessed(D, DC)) continue; Hashes.emplace_back(D, computeODRHash(D)); } diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index cbb3e8730517..b485e93f76c2 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -441,7 +441,7 @@ class ODRDeclVisitor : public ConstDeclVisitor { // Only allow a small portion of Decl's to be processed. Remove this once // all Decl's can be handled. -bool ODRHash::isDeclToBeProcessed(const Decl *D, const DeclContext *Parent) { +bool ODRHash::isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent) { if (D->isImplicit()) return false; if (D->getDeclContext() != Parent) return false; @@ -488,7 +488,7 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { // accurate count of Decl's. llvm::SmallVector Decls; for (Decl *SubDecl : Record->decls()) { -if (isDeclToBeProcessed(SubDecl, Record)) { +if (isSubDeclToBeProcessed(SubDecl, Record)) { Decls.push_back(SubDecl); if (auto *Function = dyn_cast(SubDecl)) { // Compute/Preload ODRHash into FunctionDecl. @@ -589,7 +589,7 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function, // accurate count of Decl's. llvm::SmallVector Decls; for (Decl *SubDecl : Function->decls()) { -if (isDeclToBeProcessed(SubDecl, Function)) { +if (isSubDeclToBeProcessed(SubDecl, Function)) { Decls.push_back(SubDecl); } } @@ -615,7 +615,7 @@ void ODRHash::AddEnumDecl(const EnumDecl *Enum) { // accurate count of Decl's. llvm::SmallVector Decls; for (Decl *SubDecl : Enum->decls()) { -if (isDeclToBeProcessed(SubDecl, Enum)) { +if
[clang] 9c79eab - [ODRHash] Hash `ObjCProtocolDecl` and diagnose discovered mismatches.
Author: Volodymyr Sapsai Date: 2022-10-17T16:29:52-07:00 New Revision: 9c79eab7fdd5e2bc413e9c4510f759716cd09184 URL: https://github.com/llvm/llvm-project/commit/9c79eab7fdd5e2bc413e9c4510f759716cd09184 DIFF: https://github.com/llvm/llvm-project/commit/9c79eab7fdd5e2bc413e9c4510f759716cd09184.diff LOG: [ODRHash] Hash `ObjCProtocolDecl` and diagnose discovered mismatches. Differential Revision: https://reviews.llvm.org/D130324 Added: clang/test/Modules/compare-objc-protocol.m Modified: clang/include/clang/AST/DeclObjC.h clang/include/clang/AST/ODRDiagsEmitter.h clang/include/clang/AST/ODRHash.h clang/include/clang/Basic/DiagnosticASTKinds.td clang/include/clang/Serialization/ASTReader.h clang/lib/AST/DeclObjC.cpp clang/lib/AST/ODRDiagsEmitter.cpp clang/lib/AST/ODRHash.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTReaderDecl.cpp clang/lib/Serialization/ASTWriterDecl.cpp Removed: diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 210b7adebe4cd..3d20d172dc631 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -2055,6 +2055,12 @@ class ObjCProtocolDecl : public ObjCContainerDecl, /// Referenced protocols ObjCProtocolList ReferencedProtocols; + +/// Tracks whether a ODR hash has been computed for this protocol. +unsigned HasODRHash : 1; + +/// A hash of parts of the class to help in ODR checking. +unsigned ODRHash = 0; }; /// Contains a pointer to the data associated with this class, @@ -2091,10 +2097,15 @@ class ObjCProtocolDecl : public ObjCContainerDecl, return getMostRecentDecl(); } + /// True if a valid hash is stored in ODRHash. + bool hasODRHash() const; + void setHasODRHash(bool HasHash); + public: friend class ASTDeclReader; friend class ASTDeclWriter; friend class ASTReader; + friend class ODRDiagsEmitter; static ObjCProtocolDecl *Create(ASTContext , DeclContext *DC, IdentifierInfo *Id, @@ -2250,6 +2261,9 @@ class ObjCProtocolDecl : public ObjCContainerDecl, ProtocolPropertySet , PropertyDeclOrder ) const; + /// Get precomputed ODRHash or add a new one. + unsigned getODRHash(); + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProtocol; } }; diff --git a/clang/include/clang/AST/ODRDiagsEmitter.h b/clang/include/clang/AST/ODRDiagsEmitter.h index 37e7dd4b05c9d..af345310c3a40 100644 --- a/clang/include/clang/AST/ODRDiagsEmitter.h +++ b/clang/include/clang/AST/ODRDiagsEmitter.h @@ -11,6 +11,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" @@ -44,6 +45,16 @@ class ODRDiagsEmitter { const CXXRecordDecl *SecondRecord, const struct CXXRecordDecl::DefinitionData *SecondDD) const; + /// Diagnose ODR mismatch between 2 ObjCProtocolDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + /// To compare 2 declarations with merged and identical definition data + /// you need to provide pre-merge definition data in \p SecondDD. + bool diagnoseMismatch( + const ObjCProtocolDecl *FirstProtocol, + const ObjCProtocolDecl *SecondProtocol, + const struct ObjCProtocolDecl::DefinitionData *SecondDD) const; + /// Get the best name we know for the module that owns the given /// declaration, or an empty string if the declaration is not from a module. static std::string getOwningModuleNameForDiagnostic(const Decl *D); @@ -116,6 +127,16 @@ class ODRDiagsEmitter { const VarDecl *FirstVD, const VarDecl *SecondVD) const; + /// Check if protocol lists are the same and diagnose if they are diff erent. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseSubMismatchProtocols(const ObjCProtocolList , +const ObjCContainerDecl *FirstContainer, +StringRef FirstModule, +const ObjCProtocolList , +const ObjCContainerDecl *SecondContainer, +StringRef SecondModule) const; + private: DiagnosticsEngine const ASTContext diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index 2e8593e0b8355..59b74cf477dd0 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -64,6 +64,10 @@ class ODRHash { // more information than the AddDecl class. void AddEnumDecl(const
[clang] 1783253 - [Attributes] Improve writing `ExprArgument` value.
Author: Volodymyr Sapsai Date: 2022-10-14T11:20:57-07:00 New Revision: 1783253c41f1b0ac378ab7fa4b6fe5547369c6b0 URL: https://github.com/llvm/llvm-project/commit/1783253c41f1b0ac378ab7fa4b6fe5547369c6b0 DIFF: https://github.com/llvm/llvm-project/commit/1783253c41f1b0ac378ab7fa4b6fe5547369c6b0.diff LOG: [Attributes] Improve writing `ExprArgument` value. Instead of dumping `Expr*` memory address, output `Expr` representation. Differential Revision: https://reviews.llvm.org/D135931 Added: Modified: clang/test/SemaCXX/attr-print.cpp clang/utils/TableGen/ClangAttrEmitter.cpp Removed: diff --git a/clang/test/SemaCXX/attr-print.cpp b/clang/test/SemaCXX/attr-print.cpp index d7ef42306bd39..fa8059fc8ab36 100644 --- a/clang/test/SemaCXX/attr-print.cpp +++ b/clang/test/SemaCXX/attr-print.cpp @@ -43,3 +43,6 @@ class __multiple_inheritance MultipleInheritance; // CHECK: class __virtual_inheritance VirtualInheritance; class __virtual_inheritance VirtualInheritance; + +// CHECK: typedef double *aligned_double __attribute__((align_value(64))); +typedef double * __attribute__((align_value(64))) aligned_double; diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 79590832f7d1d..b7f7e507dd6cf 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1216,6 +1216,13 @@ namespace { OS << " }\n"; } +void writeValue(raw_ostream ) const override { + OS << "\";\n"; + OS << "get" << getUpperName() + << "()->printPretty(OS, nullptr, Policy);\n"; + OS << "OS << \""; +} + void writeDump(raw_ostream ) const override {} void writeDumpChildren(raw_ostream ) const override { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] a6ebd30 - [modules] Allow to validate system headers less often with `-fmodules-validate-once-per-build-session`.
Author: Volodymyr Sapsai Date: 2022-10-12T11:10:08-07:00 New Revision: a6ebd3083dbf8aadae58f6f2a2f1071976649d56 URL: https://github.com/llvm/llvm-project/commit/a6ebd3083dbf8aadae58f6f2a2f1071976649d56 DIFF: https://github.com/llvm/llvm-project/commit/a6ebd3083dbf8aadae58f6f2a2f1071976649d56.diff LOG: [modules] Allow to validate system headers less often with `-fmodules-validate-once-per-build-session`. Make flags `-fmodules-validate-system-headers` and `-fmodules-validate-once-per-build-session` orthogonal, so they have their own independent responsibilities - if system headers should be validated and how often. rdar://8799 Differential Revision: https://reviews.llvm.org/D135232 Added: Modified: clang/lib/Serialization/ASTReader.cpp clang/test/Modules/fmodules-validate-once-per-build-session.c clang/test/Modules/validate-system-headers.m Removed: diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 45a6a474f1d93..e3e1d9eb36ae1 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2639,12 +2639,11 @@ ASTReader::ReadControlBlock(ModuleFile , // so we verify all input files. Otherwise, verify only user input // files. -unsigned N = NumUserInputs; -if (ValidateSystemInputs || -(HSOpts.ModulesValidateOncePerBuildSession && - F.InputFilesValidationTimestamp <= HSOpts.BuildSessionTimestamp && - F.Kind == MK_ImplicitModule)) - N = NumInputs; +unsigned N = ValidateSystemInputs ? NumInputs : NumUserInputs; +if (HSOpts.ModulesValidateOncePerBuildSession && +F.InputFilesValidationTimestamp > HSOpts.BuildSessionTimestamp && +F.Kind == MK_ImplicitModule) + N = NumUserInputs; for (unsigned I = 0; I < N; ++I) { InputFile IF = getInputFile(F, I+1, Complain); diff --git a/clang/test/Modules/fmodules-validate-once-per-build-session.c b/clang/test/Modules/fmodules-validate-once-per-build-session.c index 0c97342a8d70a..7ab6f78c194fd 100644 --- a/clang/test/Modules/fmodules-validate-once-per-build-session.c +++ b/clang/test/Modules/fmodules-validate-once-per-build-session.c @@ -17,8 +17,8 @@ // === // Compile the module. -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s +// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s +// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s // RUN: ls -R %t/modules-cache | grep Foo.pcm.timestamp // RUN: ls -R %t/modules-cache | grep Bar.pcm.timestamp // RUN: ls -R %t/modules-cache-user | grep Foo.pcm.timestamp @@ -30,8 +30,8 @@ // === // Use it, and make sure that we did not recompile it. -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s -// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s +// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s +// RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fmodules-validate-system-headers -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s // RUN: ls -R %t/modules-cache | grep Foo.pcm.timestamp // RUN: ls -R %t/modules-cache | grep Bar.pcm.timestamp // RUN: ls -R %t/modules-cache-user | grep Foo.pcm.timestamp @@ -54,8 +54,8 @@ // === // Use the module, and make sure that we did not recompile it if foo.h or // module.map are system
[clang] e12f6c2 - [modules] Fix error "malformed or corrupted AST file: 'SourceLocation remap refers to unknown module...'".
Author: Volodymyr Sapsai Date: 2022-09-20T17:55:37-07:00 New Revision: e12f6c26c394bd5b49e7c1e1c157bcee3a33d1de URL: https://github.com/llvm/llvm-project/commit/e12f6c26c394bd5b49e7c1e1c157bcee3a33d1de DIFF: https://github.com/llvm/llvm-project/commit/e12f6c26c394bd5b49e7c1e1c157bcee3a33d1de.diff LOG: [modules] Fix error "malformed or corrupted AST file: 'SourceLocation remap refers to unknown module...'". When a framework can be found at a new location, all references to it in the module cache become outdated. When we try to load such outdated .pcm file, we shouldn't change any already loaded and processed modules. If `Module` has `ASTFile`, it means we've read its AST block already and it is too late to undo that. If `ASTFile` is `None`, there is no value in setting it to `None` again. So we don't reset `ASTFile` in `ModuleManager::removeModules` at all. rdar://97216258 Differential Revision: https://reviews.llvm.org/D134249 Added: clang/test/Modules/dependent-module-different-location.m Modified: clang/include/clang/Basic/Module.h clang/include/clang/Serialization/ModuleManager.h clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ModuleManager.cpp Removed: diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index a2309f5d7fae..1a1feb9d4d3f 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -608,8 +608,7 @@ class Module { /// Set the serialized AST file for the top-level module of this module. void setASTFile(Optional File) { -assert((!File || !getASTFile() || getASTFile() == File) && - "file path changed"); +assert((!getASTFile() || getASTFile() == File) && "file path changed"); getTopLevelModule()->ASTFile = File; } diff --git a/clang/include/clang/Serialization/ModuleManager.h b/clang/include/clang/Serialization/ModuleManager.h index 4305bae5ee95..1623dd446036 100644 --- a/clang/include/clang/Serialization/ModuleManager.h +++ b/clang/include/clang/Serialization/ModuleManager.h @@ -250,7 +250,7 @@ class ModuleManager { std::string ); /// Remove the modules starting from First (to the end). - void removeModules(ModuleIterator First, ModuleMap *modMap); + void removeModules(ModuleIterator First); /// Add an in-memory buffer the list of known buffers void addInMemoryBuffer(StringRef FileName, diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 2716a5971c8f..ad6db3ce1993 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -4227,10 +4227,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, ReadASTCore(FileName, Type, ImportLoc, /*ImportedBy=*/nullptr, Loaded, 0, 0, ASTFileSignature(), ClientLoadCapabilities)) { -ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, -PP.getLangOpts().Modules -? ().getModuleMap() -: nullptr); +ModuleMgr.removeModules(ModuleMgr.begin() + NumModules); // If we find that any modules are unusable, the global index is going // to be out-of-date. Just remove it. diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 4fd217cf7a6e..544dac1716b0 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -249,7 +249,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, return NewlyLoaded; } -void ModuleManager::removeModules(ModuleIterator First, ModuleMap *modMap) { +void ModuleManager::removeModules(ModuleIterator First) { auto Last = end(); if (First == Last) return; @@ -280,19 +280,10 @@ void ModuleManager::removeModules(ModuleIterator First, ModuleMap *modMap) { } } - // Delete the modules and erase them from the various structures. - for (ModuleIterator victim = First; victim != Last; ++victim) { + // Delete the modules. + for (ModuleIterator victim = First; victim != Last; ++victim) Modules.erase(victim->File); -if (modMap) { - StringRef ModuleName = victim->ModuleName; - if (Module *mod = modMap->findModule(ModuleName)) { -mod->setASTFile(None); - } -} - } - - // Delete the modules. Chain.erase(Chain.begin() + (First - begin()), Chain.end()); } diff --git a/clang/test/Modules/dependent-module- diff erent-location.m b/clang/test/Modules/dependent-module- diff erent-location.m new file mode 100644 index ..f969aa9958bd --- /dev/null +++ b/clang/test/Modules/dependent-module- diff erent-location.m @@ -0,0 +1,44 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// +// At first build Stable.pcm that references
[clang] 246c5a9 - [ODRHash diagnostics] Transform method `ASTReader::diagnoseOdrViolations` into a class `ODRDiagsEmitter`. NFC.
Author: Volodymyr Sapsai Date: 2022-09-02T16:20:05-07:00 New Revision: 246c5a994b753fb52b2d3b70687039afef7a106e URL: https://github.com/llvm/llvm-project/commit/246c5a994b753fb52b2d3b70687039afef7a106e DIFF: https://github.com/llvm/llvm-project/commit/246c5a994b753fb52b2d3b70687039afef7a106e.diff LOG: [ODRHash diagnostics] Transform method `ASTReader::diagnoseOdrViolations` into a class `ODRDiagsEmitter`. NFC. Preparing to use diagnostics about ODR hash mismatches outside of ASTReader. Differential Revision: https://reviews.llvm.org/D128490 Added: Modified: clang/include/clang/AST/DeclCXX.h clang/include/clang/Serialization/ASTReader.h clang/lib/Serialization/ASTReader.cpp Removed: diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index c97301957cb60..89c7fb36aa57f 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -260,6 +260,7 @@ class CXXRecordDecl : public RecordDecl { friend class ASTWriter; friend class DeclContext; friend class LambdaExpr; + friend class ODRDiagsEmitter; friend void FunctionDecl::setPure(bool); friend void TagDecl::startDefinition(); diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 19a18a2ef4030..22f317dc6b3f7 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1845,10 +1845,6 @@ class ASTReader /// if the declaration is not from a module file. ModuleFile *getOwningModuleFile(const Decl *D); - /// Get the best name we know for the module that owns the given - /// declaration, or an empty string if the declaration is not from a module. - std::string getOwningModuleNameForDiagnostic(const Decl *D); - /// Returns the source location for the decl \p ID. SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e7dea40a16100..eef8f9fdb07f1 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9186,19 +9186,6 @@ void ASTReader::visitTopLevelModuleMaps( } } -std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { - // If we know the owning module, use it. - if (Module *M = D->getImportedOwningModule()) -return M->getFullModuleName(); - - // Otherwise, use the name of the top-level module the decl is within. - if (ModuleFile *M = getOwningModuleFile(D)) -return M->ModuleName; - - // Not from a module. - return {}; -} - void ASTReader::finishPendingActions() { while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() || !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || @@ -9446,6 +9433,114 @@ void ASTReader::finishPendingActions() { PendingMergedDefinitionsToDeduplicate.clear(); } +namespace clang { +class ODRDiagsEmitter { +public: + ODRDiagsEmitter(DiagnosticsEngine , const ASTContext , + const LangOptions ) + : Diags(Diags), Context(Context), LangOpts(LangOpts) {} + + /// Diagnose ODR mismatch between 2 FunctionDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const FunctionDecl *FirstFunction, +const FunctionDecl *SecondFunction) const; + + /// Diagnose ODR mismatch between 2 EnumDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + bool diagnoseMismatch(const EnumDecl *FirstEnum, +const EnumDecl *SecondEnum) const; + + /// Diagnose ODR mismatch between 2 CXXRecordDecl. + /// + /// Returns true if found a mismatch and diagnosed it. + /// To compare 2 declarations with merged and identical definition data + /// you need to provide pre-merge definition data in \p SecondDD. + bool + diagnoseMismatch(const CXXRecordDecl *FirstRecord, + const CXXRecordDecl *SecondRecord, + const struct CXXRecordDecl::DefinitionData *SecondDD) const; + + /// Get the best name we know for the module that owns the given + /// declaration, or an empty string if the declaration is not from a module. + static std::string getOwningModuleNameForDiagnostic(const Decl *D); + +private: + using DeclHashes = llvm::SmallVector, 4>; + + // Used with err_module_odr_violation_mismatch_decl and + // note_module_odr_violation_mismatch_decl + // This list should be the same Decl's as in ODRHash::isDeclToBeProcessed + enum ODRMismatchDecl { +EndOfClass, +PublicSpecifer, +PrivateSpecifer, +ProtectedSpecifer, +StaticAssert, +Field, +CXXMethod, +TypeAlias, +TypeDef, +Var, +Friend, +FunctionTemplate, +Other + }; + + struct DiffResult { +const Decl *FirstDecl = nullptr, *SecondDecl =
[clang] 1e4478b - Move "clang/Basic/TokenKinds.h" into a separate top-level module.
Author: Volodymyr Sapsai Date: 2022-07-22T16:26:27-07:00 New Revision: 1e4478bbea727dbbffb1023eedfc24eae7185782 URL: https://github.com/llvm/llvm-project/commit/1e4478bbea727dbbffb1023eedfc24eae7185782 DIFF: https://github.com/llvm/llvm-project/commit/1e4478bbea727dbbffb1023eedfc24eae7185782.diff LOG: Move "clang/Basic/TokenKinds.h" into a separate top-level module. Fixes modular build for clangPseudoGrammar from clang-tools-extra. Starting from https://reviews.llvm.org/D126731 clangPseudoGrammar doesn't depend on generated .inc headers but still depends on "Basic/TokenKinds.h". It means clangPseudoGrammar depends on module 'Clang_Basic' which does depend on generated .inc headers. To avoid these coarse dependencies and extra build steps, extract "clang/Basic/TokenKinds.h" into a top-level module 'Clang_Basic_TokenKinds'. rdar://97387951 Differential Revision: https://reviews.llvm.org/D130377 Added: Modified: clang/include/clang/module.modulemap Removed: diff --git a/clang/include/clang/module.modulemap b/clang/include/clang/module.modulemap index aca4d5ab919a..56c40ab0b001 100644 --- a/clang/include/clang/module.modulemap +++ b/clang/include/clang/module.modulemap @@ -71,10 +71,17 @@ module Clang_Basic { textual header "Basic/RISCVVTypes.def" textual header "Basic/Sanitizers.def" textual header "Basic/TargetCXXABI.def" - textual header "Basic/TokenKinds.def" module * { export * } } +module Clang_Basic_TokenKinds { + requires cplusplus + + header "Basic/TokenKinds.h" + textual header "Basic/TokenKinds.def" + + export * +} module Clang_CodeGen { requires cplusplus umbrella "CodeGen" module * { export * } } module Clang_Config { requires cplusplus umbrella "Config" module * { export * } } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 381fcaa - [modules] Replace `-Wauto-import` with `-Rmodule-include-translation`.
Author: Volodymyr Sapsai Date: 2022-07-21T17:42:04-07:00 New Revision: 381fcaa1365b4fd8f9682a6a1e09f5b3fd4bbfc2 URL: https://github.com/llvm/llvm-project/commit/381fcaa1365b4fd8f9682a6a1e09f5b3fd4bbfc2 DIFF: https://github.com/llvm/llvm-project/commit/381fcaa1365b4fd8f9682a6a1e09f5b3fd4bbfc2.diff LOG: [modules] Replace `-Wauto-import` with `-Rmodule-include-translation`. Diagnostic for `-Wauto-import` shouldn't be a warning because it doesn't represent a potential problem in code that should be fixed. And the emitted fix-it is likely to trigger `-Watimport-in-framework-header` which makes it challenging to have a warning-free codebase. But it is still useful to see how include directives are translated into modular imports and which module a header belongs to, that's why keep it as a remark. Keep `-Wauto-import` for now to allow a gradual migration for codebases using `-Wno-auto-import`, e.g., `-Weverything -Wno-auto-import`. rdar://79594287 Differential Revision: https://reviews.llvm.org/D130138 Added: Modified: clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticLexKinds.td clang/lib/Lex/PPDirectives.cpp clang/test/Modules/auto-module-import.m clang/test/Modules/conflicts.m clang/test/Modules/cxx20-include-translation.cpp clang/test/Modules/framework-name.m clang/test/Modules/global_index.m clang/test/Modules/implementation-of-module.m clang/test/Modules/inferred-frameworks.m clang/test/Modules/inferred-submodules.m clang/test/Modules/requires.m clang/test/Modules/requires.mm clang/test/Modules/resolution-change.m clang/test/Modules/subframeworks.m clang/test/Modules/submodules.m clang/test/VFS/real-path-found-first.m Removed: diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 53e246a39ed86..4412c93683ed3 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -35,7 +35,7 @@ def ArrayParameter : DiagGroup<"array-parameter">; def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; -def AutoImport : DiagGroup<"auto-import">; +def : DiagGroup<"auto-import">; def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; def FrameworkIncludePrivateFromPublic : DiagGroup<"framework-include-private-from-public">; @@ -490,6 +490,7 @@ def ModuleBuild : DiagGroup<"module-build">; def ModuleImport : DiagGroup<"module-import">; def ModuleConflict : DiagGroup<"module-conflict">; def ModuleFileExtension : DiagGroup<"module-file-extension">; +def ModuleIncludeDirectiveTranslation : DiagGroup<"module-include-translation">; def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">; def NewlineEOF : DiagGroup<"newline-eof">; def Nullability : DiagGroup<"nullability">; diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index dd09097044926..5d3abb1f9b702 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -851,9 +851,9 @@ def warn_framework_include_private_from_public : Warning< "public framework header includes private framework header '%0'" >, InGroup; -def warn_auto_module_import : Warning< +def remark_pp_include_directive_modular_translation : Remark< "treating #%select{include|import|include_next|__include_macros}0 as an " - "import of module '%1'">, InGroup, DefaultIgnore; + "import of module '%1'">, InGroup; def note_implicit_top_level_module_import_here : Note< "submodule of top-level module '%0' implicitly imported here">; def warn_uncovered_module_header : Warning< diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 352e1f2178193..4679cb4e7a34b 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1806,22 +1806,14 @@ static void diagnoseAutoModuleImport( Preprocessor , SourceLocation HashLoc, Token , ArrayRef> Path, SourceLocation PathEnd) { - StringRef ImportKeyword; - if (PP.getLangOpts().ObjC) -ImportKeyword = "@import"; - else if (PP.getLangOpts().ModulesTS || PP.getLangOpts().CPlusPlusModules) -ImportKeyword = "import"; - else -return; // no import syntax available - SmallString<128> PathString; for (size_t I = 0, N = Path.size(); I != N; ++I) { if (I) PathString += '.'; PathString += Path[I].first->getName(); } - int IncludeKind = 0; + int IncludeKind = 0; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { case tok::pp_include: IncludeKind = 0; @@ -1843,12 +1835,8 @@ static void diagnoseAutoModuleImport( llvm_unreachable("unknown include directive kind"); } -
[clang] f693874 - [ODRHash diagnostics] Preparation to minimize subsequent diffs. NFC.
Author: Volodymyr Sapsai Date: 2022-07-19T16:29:33-07:00 New Revision: f693874c53c1b3d3a322de98c1c7557d69157d3d URL: https://github.com/llvm/llvm-project/commit/f693874c53c1b3d3a322de98c1c7557d69157d3d DIFF: https://github.com/llvm/llvm-project/commit/f693874c53c1b3d3a322de98c1c7557d69157d3d.diff LOG: [ODRHash diagnostics] Preparation to minimize subsequent diffs. NFC. Specifically, making the following changes: * Turn lambdas calculating ODR hashes into static functions. * Move `ODRCXXRecordDifference` where it is used. * Rename some variables and move some lines of code. * Replace `auto` with explicit type when the deduced type is not mentioned. * Add `const` for unmodified objects, so we can pass them to more functions. Differential Revision: https://reviews.llvm.org/D128690 Added: Modified: clang/lib/Serialization/ASTReader.cpp Removed: diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 04ade0a3b9d0..76281d26b2ae 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9445,6 +9445,31 @@ void ASTReader::finishPendingActions() { PendingMergedDefinitionsToDeduplicate.clear(); } +static unsigned computeODRHash(QualType Ty) { + ODRHash Hasher; + Hasher.AddQualType(Ty); + return Hasher.CalculateHash(); +} + +static unsigned computeODRHash(const Stmt *S) { + ODRHash Hasher; + Hasher.AddStmt(S); + return Hasher.CalculateHash(); +} + +static unsigned computeODRHash(const Decl *D) { + assert(D); + ODRHash Hasher; + Hasher.AddSubDecl(D); + return Hasher.CalculateHash(); +} + +static unsigned computeODRHash(const TemplateArgument ) { + ODRHash Hasher; + Hasher.AddTemplateArgument(TA); + return Hasher.CalculateHash(); +} + void ASTReader::diagnoseOdrViolations() { if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() && PendingFunctionOdrMergeFailures.empty() && @@ -9584,42 +9609,6 @@ void ASTReader::diagnoseOdrViolations() { // we're producing our diagnostics. Deserializing RecursionGuard(this); - // Common code for hashing helpers. - ODRHash Hash; - auto ComputeQualTypeODRHash = [](QualType Ty) { -Hash.clear(); -Hash.AddQualType(Ty); -return Hash.CalculateHash(); - }; - - auto ComputeODRHash = [](const Stmt *S) { -assert(S); -Hash.clear(); -Hash.AddStmt(S); -return Hash.CalculateHash(); - }; - - auto ComputeSubDeclODRHash = [](const Decl *D) { -assert(D); -Hash.clear(); -Hash.AddSubDecl(D); -return Hash.CalculateHash(); - }; - - auto ComputeTemplateArgumentODRHash = [](const TemplateArgument ) { -Hash.clear(); -Hash.AddTemplateArgument(TA); -return Hash.CalculateHash(); - }; - - auto ComputeTemplateParameterListODRHash = - [](const TemplateParameterList *TPL) { -assert(TPL); -Hash.clear(); -Hash.AddTemplateParameterList(TPL); -return Hash.CalculateHash(); - }; - // Used with err_module_odr_violation_mismatch_decl and // note_module_odr_violation_mismatch_decl // This list should be the same Decl's as in ODRHash::isDeclToBeProcessed @@ -9639,49 +9628,13 @@ void ASTReader::diagnoseOdrViolations() { Other }; - // Used with err_module_odr_violation_record and - // note_module_odr_violation_record - enum ODRCXXRecordDifference { -StaticAssertCondition, -StaticAssertMessage, -StaticAssertOnlyMessage, -MethodName, -MethodDeleted, -MethodDefaulted, -MethodVirtual, -MethodStatic, -MethodVolatile, -MethodConst, -MethodInline, -MethodNumberParameters, -MethodParameterType, -MethodParameterName, -MethodParameterSingleDefaultArgument, -MethodParameterDifferentDefaultArgument, -MethodNoTemplateArguments, -MethodDifferentNumberTemplateArguments, -MethodDifferentTemplateArgument, -MethodSingleBody, -MethodDifferentBody, -FriendTypeFunction, -FriendType, -FriendFunction, -FunctionTemplateDifferentNumberParameters, -FunctionTemplateParameterDifferentKind, -FunctionTemplateParameterName, -FunctionTemplateParameterSingleDefaultArgument, -FunctionTemplateParameterDifferentDefaultArgument, -FunctionTemplateParameterDifferentType, -FunctionTemplatePackParameter, - }; - // These lambdas have the common portions of the ODR diagnostics. This // has the same return as Diag(), so addition parameters can be passed // in with operator<< - auto ODRDiagField = [this, , ]( - NamedDecl *FirstRecord, StringRef FirstModule, - StringRef SecondModule, FieldDecl *FirstField, - FieldDecl *SecondField) { + auto ODRDiagField = [this](NamedDecl *FirstRecord, StringRef FirstModule, + StringRef SecondModule, + const
[clang] 2ceb9c3 - [ODRHash diagnostics] Move common code for calculating diag locations in `DiagnoseODRMismatch` into a lambda. NFC.
Author: Volodymyr Sapsai Date: 2022-06-30T19:39:22-07:00 New Revision: 2ceb9c347f14e81a8c71d644724cefd10fce6eaf URL: https://github.com/llvm/llvm-project/commit/2ceb9c347f14e81a8c71d644724cefd10fce6eaf DIFF: https://github.com/llvm/llvm-project/commit/2ceb9c347f14e81a8c71d644724cefd10fce6eaf.diff LOG: [ODRHash diagnostics] Move common code for calculating diag locations in `DiagnoseODRMismatch` into a lambda. NFC. Differential Revision: https://reviews.llvm.org/D128489 Added: Modified: clang/lib/Serialization/ASTReader.cpp Removed: diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 37371eff28ef..d853805bf97e 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -10012,34 +10012,35 @@ void ASTReader::diagnoseOdrViolations() { } }; - auto DiagnoseODRMismatch = - [this](DiffResult , NamedDecl *FirstRecord, StringRef FirstModule, - NamedDecl *SecondRecord, StringRef SecondModule) { -SourceLocation FirstLoc; -SourceRange FirstRange; -auto *FirstTag = dyn_cast(FirstRecord); -if (DR.FirstDiffType == EndOfClass && FirstTag) { - FirstLoc = FirstTag->getBraceRange().getEnd(); -} else { - FirstLoc = DR.FirstDecl->getLocation(); - FirstRange = DR.FirstDecl->getSourceRange(); -} -Diag(FirstLoc, diag::err_module_odr_violation_mismatch_decl) -<< FirstRecord << FirstModule.empty() << FirstModule << FirstRange -<< DR.FirstDiffType; - -SourceLocation SecondLoc; -SourceRange SecondRange; -auto *SecondTag = dyn_cast(SecondRecord); -if (DR.SecondDiffType == EndOfClass && SecondTag) { - SecondLoc = SecondTag->getBraceRange().getEnd(); -} else { - SecondLoc = DR.SecondDecl->getLocation(); - SecondRange = DR.SecondDecl->getSourceRange(); -} -Diag(SecondLoc, diag::note_module_odr_violation_mismatch_decl) -<< SecondModule << SecondRange << DR.SecondDiffType; - }; + auto DiagnoseODRMismatch = [this](DiffResult , NamedDecl *FirstRecord, +StringRef FirstModule, +NamedDecl *SecondRecord, +StringRef SecondModule) { +auto GetMismatchedDeclLoc = [](const NamedDecl *Container, + ODRMismatchDecl DiffType, const Decl *D) { + SourceLocation Loc; + SourceRange Range; + auto *Tag = dyn_cast(Container); + if (DiffType == EndOfClass && Tag) { +Loc = Tag->getBraceRange().getEnd(); + } else { +Loc = D->getLocation(); +Range = D->getSourceRange(); + } + return std::make_pair(Loc, Range); +}; + +auto FirstDiagInfo = +GetMismatchedDeclLoc(FirstRecord, DR.FirstDiffType, DR.FirstDecl); +Diag(FirstDiagInfo.first, diag::err_module_odr_violation_mismatch_decl) +<< FirstRecord << FirstModule.empty() << FirstModule +<< FirstDiagInfo.second << DR.FirstDiffType; + +auto SecondDiagInfo = +GetMismatchedDeclLoc(SecondRecord, DR.SecondDiffType, DR.SecondDecl); +Diag(SecondDiagInfo.first, diag::note_module_odr_violation_mismatch_decl) +<< SecondModule << SecondDiagInfo.second << DR.SecondDiffType; + }; // Issue any pending ODR-failure diagnostics. for (auto : OdrMergeFailures) { ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 15cb180 - [ODRHash diagnostics] Split `err_module_odr_violation_mismatch_decl_diff` into per-entity diagnostics. NFC.
Author: Volodymyr Sapsai Date: 2022-06-30T18:40:46-07:00 New Revision: 15cb180dcbf84701f3af47983e223d0beaac3c9b URL: https://github.com/llvm/llvm-project/commit/15cb180dcbf84701f3af47983e223d0beaac3c9b DIFF: https://github.com/llvm/llvm-project/commit/15cb180dcbf84701f3af47983e223d0beaac3c9b.diff LOG: [ODRHash diagnostics] Split `err_module_odr_violation_mismatch_decl_diff` into per-entity diagnostics. NFC. We'll need to add more cases for Objective-C entities and adding everything to `err_module_odr_violation_mismatch_decl_diff` makes it harder to work with over time. Differential Revision: https://reviews.llvm.org/D128488 Added: Modified: clang/include/clang/Basic/DiagnosticSerializationKinds.td clang/lib/Serialization/ASTReader.cpp Removed: diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 251242e46fe5..0bd3734a4a04 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -177,20 +177,13 @@ def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " "protected access specifier|static assert|field|method|type alias|typedef|" "data member|friend declaration|function template}1">; -def err_module_odr_violation_mismatch_decl_ diff : Error< +def err_module_odr_violation_record : Error< "%q0 has diff erent definitions in diff erent modules; first diff erence is " "%select{definition in module '%2'|defined here}1 found " "%select{" "static assert with condition|" "static assert with message|" "static assert with %select{|no }4message|" - "field %4|" - "field %4 with type %5|" - "%select{non-|}5bitfield %4|" - "bitfield %4 with one width expression|" - "%select{non-|}5mutable field %4|" - "field %4 with %select{no|an}5 initalizer|" - "field %4 with an initializer|" "%select{method %5|constructor|destructor}4|" "%select{method %5|constructor|destructor}4 " "is %select{not deleted|deleted}6|" @@ -226,13 +219,6 @@ def err_module_odr_violation_mismatch_decl_ diff : Error< "with %select{no body|body}6|" "%select{method %5|constructor|destructor}4 " "with body|" - "%select{typedef|type alias}4 name %5|" - "%select{typedef|type alias}4 %5 with underlying type %6|" - "data member with name %4|" - "data member %4 with type %5|" - "data member %4 with%select{out|}5 an initializer|" - "data member %4 with an initializer|" - "data member %4 %select{is constexpr|is not constexpr}5|" "friend %select{class|function}4|" "friend %4|" "friend function %4|" @@ -250,18 +236,11 @@ def err_module_odr_violation_mismatch_decl_ diff : Error< "being a template parameter pack|" "}3">; -def note_module_odr_violation_mismatch_decl_ diff : Note<"but in '%0' found " +def note_module_odr_violation_record : Note<"but in '%0' found " "%select{" "static assert with diff erent condition|" "static assert with diff erent message|" "static assert with %select{|no }2message|" - "field %2|" - "field %2 with type %3|" - "%select{non-|}3bitfield %2|" - "bitfield %2 with diff erent width expression|" - "%select{non-|}3mutable field %2|" - "field %2 with %select{no|an}3 initializer|" - "field %2 with a diff erent initializer|" "%select{method %3|constructor|destructor}2|" "%select{method %3|constructor|destructor}2 " "is %select{not deleted|deleted}4|" @@ -297,13 +276,6 @@ def note_module_odr_violation_mismatch_decl_ diff : Note<"but in '%0' found " "with %select{no body|body}4|" "%select{method %3|constructor|destructor}2 " "with diff erent body|" - "%select{typedef|type alias}2 name %3|" - "%select{typedef|type alias}2 %3 with diff erent underlying type %4|" - "data member with name %2|" - "data member %2 with diff erent type %3|" - "data member %2 with%select{out|}3 an initializer|" - "data member %2 with a diff erent initializer|" - "data member %2 %select{is constexpr|is not constexpr}3|" "friend %select{class|function}2|" "friend %2|" "friend function %2|" @@ -321,6 +293,61 @@ def note_module_odr_violation_mismatch_decl_ diff : Note<"but in '%0' found " "being a template parameter pack|" "}1">; +def err_module_odr_violation_field : Error< + "%q0 has diff erent definitions in diff erent modules; first diff erence is " + "%select{definition in module '%2'|defined here}1 found " + "%select{" + "field %4|" + "field %4 with type %5|" + "%select{non-|}5bitfield %4|" + "bitfield %4 with one width expression|" + "%select{non-|}5mutable field %4|" + "field %4 with %select{no|an}5 initalizer|" + "field %4 with an initializer" + "}3">; +def note_module_odr_violation_field : Note<"but in '%0' found " + "%select{" + "field %2|" + "field %2 with type %3|" + "%select{non-|}3bitfield %2|"
[clang] 3514131 - [ODRHash diagnostics] Fix typos. NFC.
Author: Volodymyr Sapsai Date: 2022-06-29T14:59:37-07:00 New Revision: 3514131219ffdc94c0c61c5b585b53e97501fbea URL: https://github.com/llvm/llvm-project/commit/3514131219ffdc94c0c61c5b585b53e97501fbea DIFF: https://github.com/llvm/llvm-project/commit/3514131219ffdc94c0c61c5b585b53e97501fbea.diff LOG: [ODRHash diagnostics] Fix typos. NFC. Added: Modified: clang/include/clang/Basic/DiagnosticSerializationKinds.td clang/lib/Serialization/ASTReader.cpp clang/test/Modules/odr_hash.cpp Removed: diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 33eba6cf0c3f2..251242e46fe5d 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -355,7 +355,7 @@ def err_module_odr_violation_enum : Error< "enum with specified type %4|" "enum with %4 element%s4|" "%ordinal4 element has name %5|" - "%ordinal4 element %5 %select{has|does not have}6 an initilizer|" + "%ordinal4 element %5 %select{has|does not have}6 an initializer|" "%ordinal4 element %5 has an initializer|" "}3">; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index f15e0bcce3318..6bfd81634f50b 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -10636,7 +10636,7 @@ void ASTReader::diagnoseOdrViolations() { // Compare the hash generated to the hash stored. A diff erence means // that a body was present in the original source. Due to merging, -// the stardard way of detecting a body will not work. +// the standard way of detecting a body will not work. const bool HasFirstBody = ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash(); const bool HasSecondBody = @@ -11166,8 +11166,8 @@ void ASTReader::diagnoseOdrViolations() { DifferentSpecifiedTypes, DifferentNumberEnumConstants, EnumConstantName, - EnumConstantSingleInitilizer, - EnumConstantDifferentInitilizer, + EnumConstantSingleInitializer, + EnumConstantDifferentInitializer, }; // If we've already pointed out a specific problem with this enum, don't @@ -11301,18 +11301,18 @@ void ASTReader::diagnoseOdrViolations() { continue; if (!FirstInit || !SecondInit) { - ODRDiagError(FirstEnumConstant, EnumConstantSingleInitilizer) + ODRDiagError(FirstEnumConstant, EnumConstantSingleInitializer) << I + 1 << FirstEnumConstant << (FirstInit != nullptr); - ODRDiagNote(SecondEnumConstant, EnumConstantSingleInitilizer) + ODRDiagNote(SecondEnumConstant, EnumConstantSingleInitializer) << I + 1 << SecondEnumConstant << (SecondInit != nullptr); Diagnosed = true; break; } if (ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) { - ODRDiagError(FirstEnumConstant, EnumConstantDifferentInitilizer) + ODRDiagError(FirstEnumConstant, EnumConstantDifferentInitializer) << I + 1 << FirstEnumConstant; - ODRDiagNote(SecondEnumConstant, EnumConstantDifferentInitilizer) + ODRDiagNote(SecondEnumConstant, EnumConstantDifferentInitializer) << I + 1 << SecondEnumConstant; Diagnosed = true; break; diff --git a/clang/test/Modules/odr_hash.cpp b/clang/test/Modules/odr_hash.cpp index 81899943bc64c..aed08c1a3a044 100644 --- a/clang/test/Modules/odr_hash.cpp +++ b/clang/test/Modules/odr_hash.cpp @@ -3300,7 +3300,7 @@ enum E7 { x71 = 0 }; enum E7 { x71 }; #else E7 e7; -// expected-error@second.h:* {{'Enums::E7' has diff erent definitions in diff erent modules; definition in module 'SecondModule' first diff erence is 1st element 'x71' has an initilizer}} +// expected-error@second.h:* {{'Enums::E7' has diff erent definitions in diff erent modules; definition in module 'SecondModule' first diff erence is 1st element 'x71' has an initializer}} // expected-note@first.h:* {{but in 'FirstModule' found 1st element 'x71' does not have an initializer}} #endif @@ -3310,7 +3310,7 @@ enum E8 { x81 }; enum E8 { x81 = 0 }; #else E8 e8; -// expected-error@second.h:* {{'Enums::E8' has diff erent definitions in diff erent modules; definition in module 'SecondModule' first diff erence is 1st element 'x81' does not have an initilizer}} +// expected-error@second.h:* {{'Enums::E8' has diff erent definitions in diff erent modules; definition in module 'SecondModule' first diff erence is 1st element 'x81' does not have an initializer}} // expected-note@first.h:* {{but in 'FirstModule' found 1st element 'x81' has an initializer}} #endif ___ cfe-commits
[clang] 017c068 - [ODRHash diagnostics] Move repetetive code at lambda calls into lambdas themselves. NFC.
Author: Volodymyr Sapsai Date: 2022-06-29T13:24:55-07:00 New Revision: 017c068f7899b895e654c8efc1c4d02d940dbf8a URL: https://github.com/llvm/llvm-project/commit/017c068f7899b895e654c8efc1c4d02d940dbf8a DIFF: https://github.com/llvm/llvm-project/commit/017c068f7899b895e654c8efc1c4d02d940dbf8a.diff LOG: [ODRHash diagnostics] Move repetetive code at lambda calls into lambdas themselves. NFC. It helps to avoid copy-paste mistakes and makes custom code paths more noticeable. Not funnelling all diagnostic through `ODRDiagDeclError` because plan to break down `err_module_odr_violation_mismatch_decl_diff` into smaller pieces instead of making it bigger and bigger. Differential Revision: https://reviews.llvm.org/D128487 Added: Modified: clang/lib/Serialization/ASTReader.cpp Removed: diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 36d7f4186af68..f15e0bcce3318 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9690,34 +9690,29 @@ void ASTReader::diagnoseOdrViolations() { // These lambdas have the common portions of the ODR diagnostics. This // has the same return as Diag(), so addition parameters can be passed // in with operator<< - auto ODRDiagDeclError = [this](NamedDecl *FirstRecord, StringRef FirstModule, - SourceLocation Loc, SourceRange Range, - ODRMismatchDeclDifference DiffType) { -return Diag(Loc, diag::err_module_odr_violation_mismatch_decl_ diff ) - << FirstRecord << FirstModule.empty() << FirstModule << Range - << DiffType; - }; - auto ODRDiagDeclNote = [this](StringRef SecondModule, SourceLocation Loc, -SourceRange Range, ODRMismatchDeclDifference DiffType) { -return Diag(Loc, diag::note_module_odr_violation_mismatch_decl_ diff ) - << SecondModule << Range << DiffType; - }; - - auto ODRDiagField = [this, , , - , ]( + auto ODRDiagField = [this, , ]( NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule, FieldDecl *FirstField, FieldDecl *SecondField) { +auto DiagError = [FirstRecord, FirstField, FirstModule, + this](ODRMismatchDeclDifference DiffType) { + return Diag(FirstField->getLocation(), + diag::err_module_odr_violation_mismatch_decl_ diff ) + << FirstRecord << FirstModule.empty() << FirstModule + << FirstField->getSourceRange() << DiffType; +}; +auto DiagNote = [SecondField, SecondModule, + this](ODRMismatchDeclDifference DiffType) { + return Diag(SecondField->getLocation(), + diag::note_module_odr_violation_mismatch_decl_ diff ) + << SecondModule << SecondField->getSourceRange() << DiffType; +}; + IdentifierInfo *FirstII = FirstField->getIdentifier(); IdentifierInfo *SecondII = SecondField->getIdentifier(); if (FirstII->getName() != SecondII->getName()) { - ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(), - FirstField->getSourceRange(), FieldName) - << FirstII; - ODRDiagDeclNote(SecondModule, SecondField->getLocation(), - SecondField->getSourceRange(), FieldName) - << SecondII; - + DiagError(FieldName) << FirstII; + DiagNote(FieldName) << SecondII; return true; } @@ -9728,25 +9723,16 @@ void ASTReader::diagnoseOdrViolations() { QualType SecondType = SecondField->getType(); if (ComputeQualTypeODRHash(FirstType) != ComputeQualTypeODRHash(SecondType)) { - ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(), - FirstField->getSourceRange(), FieldTypeName) - << FirstII << FirstType; - ODRDiagDeclNote(SecondModule, SecondField->getLocation(), - SecondField->getSourceRange(), FieldTypeName) - << SecondII << SecondType; - + DiagError(FieldTypeName) << FirstII << FirstType; + DiagNote(FieldTypeName) << SecondII << SecondType; return true; } const bool IsFirstBitField = FirstField->isBitField(); const bool IsSecondBitField = SecondField->isBitField(); if (IsFirstBitField != IsSecondBitField) { - ODRDiagDeclError(FirstRecord, FirstModule, FirstField->getLocation(), - FirstField->getSourceRange(), FieldSingleBitField) - << FirstII << IsFirstBitField; - ODRDiagDeclNote(SecondModule, SecondField->getLocation(), - SecondField->getSourceRange(), FieldSingleBitField) - << SecondII << IsSecondBitField; + DiagError(FieldSingleBitField) << FirstII <<
[clang] f3defc2 - [ODRHash][NFC] Add missing 'select' case for `ODRMismatchDecl`.
Author: Volodymyr Sapsai Date: 2022-05-30T10:07:03-07:00 New Revision: f3defc23488eb29c69d2a33c0c5b652c874fb0f3 URL: https://github.com/llvm/llvm-project/commit/f3defc23488eb29c69d2a33c0c5b652c874fb0f3 DIFF: https://github.com/llvm/llvm-project/commit/f3defc23488eb29c69d2a33c0c5b652c874fb0f3.diff LOG: [ODRHash][NFC] Add missing 'select' case for `ODRMismatchDecl`. No test changes because `err_module_odr_violation_mismatch_decl_unknown` is a catch-all when custom diagnostic is missing. And missing custom diagnostic we should fix by implementing it, not by improving the general case. But if we pass enum value not covered by 'select', clang can crash, so protect against that. Differential Revision: https://reviews.llvm.org/D126566 Added: Modified: clang/include/clang/Basic/DiagnosticSerializationKinds.td Removed: diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index 3fcdb616bd21a..33eba6cf0c3f2 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -375,12 +375,14 @@ def err_module_odr_violation_mismatch_decl_unknown : Error< "%q0 %select{with definition in module '%2'|defined here}1 has diff erent " "definitions in diff erent modules; first diff erence is this " "%select{static assert|field|method|type alias|typedef|data member|" - "friend declaration|unexpected decl}3">; + "friend declaration|function template|" + "unexpected decl}3">; def note_module_odr_violation_mismatch_decl_unknown : Note< "but in '%0' found " "%select{ diff erent static assert| diff erent field| diff erent method|" " diff erent type alias| diff erent typedef| diff erent data member|" - " diff erent friend declaration|another unexpected decl}1">; + " diff erent friend declaration| diff erent function template|" + "another unexpected decl}1">; def warn_duplicate_module_file_extension : Warning< "duplicate module file extension block name '%0'">, ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 3b762b3 - [clang][NFC] In parts of Objective-C Sema use Obj-C-specific types instead of `Decl`.
Author: Volodymyr Sapsai Date: 2022-05-05T19:19:41-07:00 New Revision: 3b762b3ab8d205cd6a7d42c96d39d5f4f701f2ab URL: https://github.com/llvm/llvm-project/commit/3b762b3ab8d205cd6a7d42c96d39d5f4f701f2ab DIFF: https://github.com/llvm/llvm-project/commit/3b762b3ab8d205cd6a7d42c96d39d5f4f701f2ab.diff LOG: [clang][NFC] In parts of Objective-C Sema use Obj-C-specific types instead of `Decl`. Differential Revision: https://reviews.llvm.org/D124285 Added: Modified: clang/include/clang/Parse/Parser.h clang/include/clang/Sema/Sema.h clang/lib/Parse/ParseObjc.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclObjC.cpp Removed: diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 8f28eb30ad1dc..99fe375f9145f 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -447,7 +447,9 @@ class Parser : public CodeCompletionHandler { return Actions.incrementMSManglingNumber(); } - Decl *getObjCDeclContext() const { return Actions.getObjCDeclContext(); } + ObjCContainerDecl *getObjCDeclContext() const { +return Actions.getObjCDeclContext(); + } // Type forwarding. All of these are statically 'void*', but they may all be // diff erent actual classes based on the actions in place. @@ -1001,18 +1003,18 @@ class Parser : public CodeCompletionHandler { /// back. class ObjCDeclContextSwitch { Parser -Decl *DC; +ObjCContainerDecl *DC; SaveAndRestore WithinObjCContainer; public: explicit ObjCDeclContextSwitch(Parser ) : P(p), DC(p.getObjCDeclContext()), WithinObjCContainer(P.ParsingInObjCContainer, DC != nullptr) { if (DC) - P.Actions.ActOnObjCTemporaryExitContainerContext(cast(DC)); +P.Actions.ActOnObjCTemporaryExitContainerContext(DC); } ~ObjCDeclContextSwitch() { if (DC) -P.Actions.ActOnObjCReenterContainerContext(cast(DC)); +P.Actions.ActOnObjCReenterContainerContext(DC); } }; @@ -1614,11 +1616,12 @@ class Parser : public CodeCompletionHandler { SmallVectorImpl , SourceLocation , bool mayBeProtocolList = true); - void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc, + void HelperActionsForIvarDeclarations(ObjCContainerDecl *interfaceDecl, +SourceLocation atLoc, BalancedDelimiterTracker , SmallVectorImpl , bool RBraceMissing); - void ParseObjCClassInstanceVariables(Decl *interfaceDecl, + void ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl, tok::ObjCKeywordKind visibility, SourceLocation atLoc); bool ParseObjCProtocolReferences(SmallVectorImpl , diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 44fbffdda3900..27603f0b891f3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3285,7 +3285,7 @@ class Sema final { /// Invoked when we enter a tag definition that we're skipping. SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD); - Decl *ActOnObjCContainerStartDefinition(Decl *IDecl); + void ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl); /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a /// C++ record definition's base-specifiers clause and are starting its @@ -3309,8 +3309,8 @@ class Sema final { /// scope for parsing/looking-up C constructs. /// /// Must be followed by a call to \see ActOnObjCReenterContainerContext - void ActOnObjCTemporaryExitContainerContext(DeclContext *DC); - void ActOnObjCReenterContainerContext(DeclContext *DC); + void ActOnObjCTemporaryExitContainerContext(ObjCContainerDecl *ObjCCtx); + void ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx); /// ActOnTagDefinitionError - Invoked when there was an unrecoverable /// error parsing the definition of a tag. @@ -9738,7 +9738,7 @@ class Sema final { SourceLocation rAngleLoc); void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList); - Decl *ActOnStartClassInterface( + ObjCInterfaceDecl *ActOnStartClassInterface( Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, IdentifierInfo *SuperName, SourceLocation SuperLoc, @@ -9772,13 +9772,13 @@ class Sema final { SourceLocation , SourceLocation PrevLoc, const ObjCList ); - Decl *ActOnStartProtocolInterface( + ObjCProtocolDecl *ActOnStartProtocolInterface( SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
[clang] d32c685 - [modules] Merge equivalent extensions and diagnose ivar redeclarations for extensions loaded from different modules.
Author: Volodymyr Sapsai Date: 2022-04-27T15:52:59-07:00 New Revision: d32c685e1012785c0d2824214740f973d30e1daa URL: https://github.com/llvm/llvm-project/commit/d32c685e1012785c0d2824214740f973d30e1daa DIFF: https://github.com/llvm/llvm-project/commit/d32c685e1012785c0d2824214740f973d30e1daa.diff LOG: [modules] Merge equivalent extensions and diagnose ivar redeclarations for extensions loaded from different modules. Emitting metadata for the same ivar multiple times can lead to miscompilations. Objective-C runtime adds offsets to calculate ivar position in memory and presence of duplicate offsets causes wrong final position thus overwriting unrelated memory. Such a situation is impossible with modules disabled as clang diagnoses ivar redeclarations during sema checks after parsing (`Sema::ActOnFields`). Fix the case with modules enabled by checking during deserialization if ivar is already declared. We also support a use case where the same category ends up in multiple modules. We don't want to treat this case as ivar redeclaration and instead merge corresponding ivars. rdar://83468070 Differential Revision: https://reviews.llvm.org/D121177 Added: clang/test/Modules/merge-extension-ivars.m clang/test/Modules/redecl-ivars.m Modified: clang/include/clang/AST/DeclObjC.h clang/include/clang/Serialization/ASTReader.h clang/lib/AST/DeclObjC.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTReaderDecl.cpp Removed: diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 110b7dc0c6f2..59a2cf5de234 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -1951,7 +1951,10 @@ class ObjCIvarDecl : public FieldDecl { /// in; this is either the interface where the ivar was declared, or the /// interface the ivar is conceptually a part of in the case of synthesized /// ivars. - const ObjCInterfaceDecl *getContainingInterface() const; + ObjCInterfaceDecl *getContainingInterface(); + const ObjCInterfaceDecl *getContainingInterface() const { +return const_cast(this)->getContainingInterface(); + } ObjCIvarDecl *getNextIvar() { return NextIvar; } const ObjCIvarDecl *getNextIvar() const { return NextIvar; } @@ -2885,15 +2888,16 @@ ObjCInterfaceDecl::filtered_category_iterator::operator++() { } inline bool ObjCInterfaceDecl::isVisibleCategory(ObjCCategoryDecl *Cat) { - return Cat->isUnconditionallyVisible(); + return !Cat->isInvalidDecl() && Cat->isUnconditionallyVisible(); } inline bool ObjCInterfaceDecl::isVisibleExtension(ObjCCategoryDecl *Cat) { - return Cat->IsClassExtension() && Cat->isUnconditionallyVisible(); + return !Cat->isInvalidDecl() && Cat->IsClassExtension() && + Cat->isUnconditionallyVisible(); } inline bool ObjCInterfaceDecl::isKnownExtension(ObjCCategoryDecl *Cat) { - return Cat->IsClassExtension(); + return !Cat->isInvalidDecl() && Cat->IsClassExtension(); } } // namespace clang diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index d46a6c4500f4..8e8e40a5cd37 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1106,6 +1106,18 @@ class ASTReader /// been completed. std::deque PendingDeclContextInfos; + template + using DuplicateObjCDecls = std::pair; + + /// When resolving duplicate ivars from Objective-C extensions we don't error + /// out immediately but check if can merge identical extensions. Not checking + /// extensions for equality immediately because ivar deserialization isn't + /// over yet at that point. + llvm::SmallMapVector, + llvm::SmallVector, 4>, + 2> + PendingObjCExtensionIvarRedeclarations; + /// The set of NamedDecls that have been loaded, but are members of a /// context that has been merged into another context where the corresponding /// declaration is either missing or has not yet been loaded. diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index f15dd78929e2..15c545b59c81 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -1647,6 +1647,11 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { ObjCIvarDecl *curIvar = nullptr; if (!data().IvarList) { +// Force ivar deserialization upfront, before building IvarList. +(void)ivar_empty(); +for (const auto *Ext : known_extensions()) { + (void)Ext->ivar_empty(); +} if (!ivar_empty()) { ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); data().IvarList = *I; ++I; @@ -1838,8 +1843,8 @@ ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext , unsigned ID) { ObjCIvarDecl::None, nullptr, false); } -const
[clang] a7f9f2f - [fixup] Handle enum constant `Lang_OBJC` introduced in 4604db94.
Author: Volodymyr Sapsai Date: 2022-04-22T17:59:17-07:00 New Revision: a7f9f2fea506fa213e4ce9c6230a816cd5bcfa38 URL: https://github.com/llvm/llvm-project/commit/a7f9f2fea506fa213e4ce9c6230a816cd5bcfa38 DIFF: https://github.com/llvm/llvm-project/commit/a7f9f2fea506fa213e4ce9c6230a816cd5bcfa38.diff LOG: [fixup] Handle enum constant `Lang_OBJC` introduced in 4604db94. Added: Modified: clang/lib/Testing/CommandLineArgs.cpp Removed: diff --git a/clang/lib/Testing/CommandLineArgs.cpp b/clang/lib/Testing/CommandLineArgs.cpp index c04702f689028..bf517e2dd312e 100644 --- a/clang/lib/Testing/CommandLineArgs.cpp +++ b/clang/lib/Testing/CommandLineArgs.cpp @@ -72,6 +72,9 @@ std::vector getCC1ArgsForTesting(TestLanguage Lang) { case Lang_CXX20: Args = {"-std=c++20"}; break; + case Lang_OBJC: +Args = {"-xobjective-c"}; +break; case Lang_OBJCXX: Args = {"-xobjective-c++"}; break; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 4604db9 - [ASTStructuralEquivalence] Add support for comparing ObjCCategoryDecl.
Author: Volodymyr Sapsai Date: 2022-04-22T16:51:19-07:00 New Revision: 4604db9493ffb22e1f411d907f163bf021193d84 URL: https://github.com/llvm/llvm-project/commit/4604db9493ffb22e1f411d907f163bf021193d84 DIFF: https://github.com/llvm/llvm-project/commit/4604db9493ffb22e1f411d907f163bf021193d84.diff LOG: [ASTStructuralEquivalence] Add support for comparing ObjCCategoryDecl. Differential Revision: https://reviews.llvm.org/D121176 Added: Modified: clang/include/clang/Testing/CommandLineArgs.h clang/lib/AST/ASTStructuralEquivalence.cpp clang/lib/Testing/CommandLineArgs.cpp clang/unittests/AST/MatchVerifier.h clang/unittests/AST/StructuralEquivalenceTest.cpp Removed: diff --git a/clang/include/clang/Testing/CommandLineArgs.h b/clang/include/clang/Testing/CommandLineArgs.h index fe2103a3dce21..e668781ee2ce1 100644 --- a/clang/include/clang/Testing/CommandLineArgs.h +++ b/clang/include/clang/Testing/CommandLineArgs.h @@ -29,6 +29,7 @@ enum TestLanguage { Lang_CXX17, Lang_CXX20, Lang_OpenCL, + Lang_OBJC, Lang_OBJCXX }; diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 05f3470a179d2..b15036a11ad92 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1242,10 +1242,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , return true; } -/// Determine structural equivalence of two fields. static bool IsStructurallyEquivalent(StructuralEquivalenceContext , - FieldDecl *Field1, FieldDecl *Field2) { - const auto *Owner2 = cast(Field2->getDeclContext()); + FieldDecl *Field1, FieldDecl *Field2, + QualType Owner2Type) { + const auto *Owner2 = cast(Field2->getDeclContext()); // For anonymous structs/unions, match up the anonymous struct/union type // declarations directly, so that we don't go off searching for anonymous @@ -1265,7 +1265,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , Context.Diag2( Owner2->getLocation(), Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) - << Context.ToCtx.getTypeDeclType(Owner2); + << Owner2Type; Context.Diag2(Field2->getLocation(), diag::note_odr_field_name) << Field2->getDeclName(); Context.Diag1(Field1->getLocation(), diag::note_odr_field_name) @@ -1280,7 +1280,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , Context.Diag2( Owner2->getLocation(), Context.getApplicableDiagnostic(diag::err_odr_tag_type_inconsistent)) - << Context.ToCtx.getTypeDeclType(Owner2); + << Owner2Type; Context.Diag2(Field2->getLocation(), diag::note_odr_field) << Field2->getDeclName() << Field2->getType(); Context.Diag1(Field1->getLocation(), diag::note_odr_field) @@ -1296,6 +1296,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , return true; } +/// Determine structural equivalence of two fields. +static bool IsStructurallyEquivalent(StructuralEquivalenceContext , + FieldDecl *Field1, FieldDecl *Field2) { + const auto *Owner2 = cast(Field2->getDeclContext()); + return IsStructurallyEquivalent(Context, Field1, Field2, + Context.ToCtx.getTypeDeclType(Owner2)); +} + /// Determine structural equivalence of two methods. static bool IsStructurallyEquivalent(StructuralEquivalenceContext , CXXMethodDecl *Method1, @@ -1610,6 +1618,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , } // Check the fields for consistency. + QualType D2Type = Context.ToCtx.getTypeDeclType(D2); RecordDecl::field_iterator Field2 = D2->field_begin(), Field2End = D2->field_end(); for (RecordDecl::field_iterator Field1 = D1->field_begin(), @@ -1628,7 +1637,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , return false; } -if (!IsStructurallyEquivalent(Context, *Field1, *Field2)) +if (!IsStructurallyEquivalent(Context, *Field1, *Field2, D2Type)) return false; } @@ -1934,6 +1943,126 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext , return true; } +static bool IsStructurallyEquivalent(StructuralEquivalenceContext , + ObjCIvarDecl *D1, ObjCIvarDecl *D2, + QualType Owner2Type) { + if (D1->getAccessControl() != D2->getAccessControl()) +return false; + + return IsStructurallyEquivalent(Context, cast(D1), + cast(D2), Owner2Type); +} + +static bool
[clang] 29444f0 - [modules] Merge ObjC interface ivars with anonymous types.
Author: Volodymyr Sapsai Date: 2022-04-04T18:48:30-07:00 New Revision: 29444f0444c6d3586969fd6fbe49c8188c02c244 URL: https://github.com/llvm/llvm-project/commit/29444f0444c6d3586969fd6fbe49c8188c02c244 DIFF: https://github.com/llvm/llvm-project/commit/29444f0444c6d3586969fd6fbe49c8188c02c244.diff LOG: [modules] Merge ObjC interface ivars with anonymous types. Without the fix ivars with anonymous types can trigger errors like > error: 'TestClass::structIvar' from module 'Target' is not present in > definition of 'TestClass' provided earlier > [...] > note: declaration of 'structIvar' does not match It happens because types of ivars from different modules are considered to be different. And it is caused by not merging anonymous `TagDecl` from different modules. To fix that I've changed `serialization::needsAnonymousDeclarationNumber` to handle anonymous `TagDecl` inside `ObjCInterfaceDecl`. But that's not sufficient as C code inside `ObjCInterfaceDecl` doesn't use interface decl as a decl context but switches to its parent (TranslationUnit in most cases). I'm changing that to make `ObjCContainerDecl` the lexical decl context but keeping the semantic decl context intact. Test "check-dup-decls-inside-objc.m" doesn't reflect a change in functionality but captures the existing behavior to prevent regressions. rdar://85563013 Differential Revision: https://reviews.llvm.org/D118525 Added: clang/test/Modules/merge-anon-record-definition-in-objc.m clang/test/SemaObjC/check-dup-decls-inside-objc.m Modified: clang/lib/Parse/ParseObjc.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Serialization/ASTCommon.cpp clang/lib/Serialization/ASTReaderDecl.cpp clang/test/AST/ast-dump-decl.mm Removed: diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 719513e7bda09..c56fcb8cc3cfe 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1871,9 +1871,9 @@ void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocatio if (!RBraceMissing) T.consumeClose(); - Actions.ActOnObjCContainerStartDefinition(interfaceDecl); + assert(getObjCDeclContext() == interfaceDecl && + "Ivars should have interfaceDecl as their decl context"); Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls); - Actions.ActOnObjCContainerFinishDefinition(); // Call ActOnFields() even if we don't have any decls. This is useful // for code rewriting tools that need to be aware of the empty list. Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, @@ -1908,8 +1908,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, assert(Tok.is(tok::l_brace) && "expected {"); SmallVector AllIvarDecls; - ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope); - ObjCDeclContextSwitch ObjCDC(*this); + ParseScope ClassScope(this, Scope::DeclScope | Scope::ClassScope); BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); @@ -1973,13 +1972,13 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } auto ObjCIvarCallback = [&](ParsingFieldDeclarator ) { - Actions.ActOnObjCContainerStartDefinition(interfaceDecl); + assert(getObjCDeclContext() == interfaceDecl && + "Ivar should have interfaceDecl as its decl context"); // Install the declarator into the interface decl. FD.D.setObjCIvar(true); Decl *Field = Actions.ActOnIvar( getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D, FD.BitfieldSize, visibility); - Actions.ActOnObjCContainerFinishDefinition(); if (Field) AllIvarDecls.push_back(Field); FD.complete(Field); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1e25346fde6f6..0b5b530bc756c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16059,9 +16059,20 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // with C structs, unions, and enums when looking for a matching // tag declaration or definition. See the similar lookup tweak // in Sema::LookupName; is there a better way to deal with this? - while (isa(SearchDC) || isa(SearchDC)) + while (isa(SearchDC)) +SearchDC = SearchDC->getParent(); +} else if (getLangOpts().CPlusPlus) { + // Inside ObjCContainer want to keep it as a lexical decl context but go + // past it (most often to TranslationUnit) to find the semantic decl + // context. + while (isa(SearchDC)) SearchDC = SearchDC->getParent(); } + } else if (getLangOpts().CPlusPlus) { +// Don't use ObjCContainerDecl as the semantic decl context for anonymous +// TagDecl the same way as we skip it for named TagDecl. +while (isa(SearchDC)) + SearchDC =
[clang] a621b0a - [clang][NFC] Remove unused parameter in `Sema::ActOnDuplicateDefinition`.
Author: Volodymyr Sapsai Date: 2022-03-28T12:07:28-07:00 New Revision: a621b0af9cd03bce079a2a6f4d72a6471ca1bb85 URL: https://github.com/llvm/llvm-project/commit/a621b0af9cd03bce079a2a6f4d72a6471ca1bb85 DIFF: https://github.com/llvm/llvm-project/commit/a621b0af9cd03bce079a2a6f4d72a6471ca1bb85.diff LOG: [clang][NFC] Remove unused parameter in `Sema::ActOnDuplicateDefinition`. Added: Modified: clang/include/clang/Sema/Sema.h clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Sema/SemaDecl.cpp Removed: diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 817df4e108433..53ac1d011d9e1 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3254,8 +3254,7 @@ class Sema final { /// 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 , Decl *Prev, -SkipBodyInfo ); + bool ActOnDuplicateDefinition(Decl *Prev, SkipBodyInfo ); typedef void *SkippedDefinitionContext; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c0fb7e0df1b61..f07758197205f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4870,7 +4870,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec , Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl; ParseEnumBody(StartLoc, D); if (SkipBody.CheckSameAsPrevious && -!Actions.ActOnDuplicateDefinition(DS, TagDecl, SkipBody)) { +!Actions.ActOnDuplicateDefinition(TagDecl, SkipBody)) { DS.SetTypeSpecError(); return; } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 1bb43f56422d7..342ee896bee18 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2049,8 +2049,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Parse the definition body. ParseStructUnionBody(StartLoc, TagType, cast(D)); if (SkipBody.CheckSameAsPrevious && - !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(), -SkipBody)) { + !Actions.ActOnDuplicateDefinition(TagOrTempResult.get(), SkipBody)) { DS.SetTypeSpecError(); return; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 4051ab29fb26f..298d4fc17617b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16703,8 +16703,7 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { AddPushedVisibilityAttribute(Tag); } -bool Sema::ActOnDuplicateDefinition(DeclSpec , Decl *Prev, -SkipBodyInfo ) { +bool Sema::ActOnDuplicateDefinition(Decl *Prev, SkipBodyInfo ) { if (!hasStructuralCompatLayout(Prev, SkipBody.New)) return false; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] fa4a0f1 - [modules] Add a flag for TagDecl if it was a definition demoted to a declaration.
Author: Volodymyr Sapsai Date: 2022-02-14T16:04:40-08:00 New Revision: fa4a0f1d31e2f797c3e27eb7cad15755e46a4726 URL: https://github.com/llvm/llvm-project/commit/fa4a0f1d31e2f797c3e27eb7cad15755e46a4726 DIFF: https://github.com/llvm/llvm-project/commit/fa4a0f1d31e2f797c3e27eb7cad15755e46a4726.diff LOG: [modules] Add a flag for TagDecl if it was a definition demoted to a declaration. For redeclaration chains we maintain an invariant of having only a single definition in the chain. In a single translation unit we make sure not to create duplicates. But modules are separate translation units and they can contain definitions for the same symbol independently. When we load such modules together, we need to demote duplicate definitions to keep the AST invariants. Some AST clients are interested in distinguishing declaration-that-was-demoted-from-definition and declaration-that-was-never-a-definition. For that purpose introducing `IsThisDeclarationADemotedDefinition`. No functional change intended. rdar://84677782 Differential Revision: https://reviews.llvm.org/D118855 Added: Modified: clang/include/clang/AST/Decl.h clang/include/clang/AST/DeclBase.h clang/lib/AST/Decl.cpp clang/lib/Serialization/ASTReaderDecl.cpp Removed: diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 862e8899d2751..7611bac83419d 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3486,6 +3486,24 @@ class TagDecl : public TypeDecl, /// parameters. bool isDependentType() const { return isDependentContext(); } + /// Whether this declaration was a definition in some module but was forced + /// to be a declaration. + /// + /// Useful for clients checking if a module has a definition of a specific + /// symbol and not interested in the final AST with deduplicated definitions. + bool isThisDeclarationADemotedDefinition() const { +return TagDeclBits.IsThisDeclarationADemotedDefinition; + } + + /// Mark a definition as a declaration and maintain information it _was_ + /// a definition. + void demoteThisDefinitionToDeclaration() { +assert(isCompleteDefinition() && + "Should demote definitions only, not forward declarations"); +setCompleteDefinition(false); +TagDeclBits.IsThisDeclarationADemotedDefinition = true; + } + /// Starts the definition of this tag declaration. /// /// This method should be invoked at the beginning of the definition diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 06d2f17d14300..a89f776248c1f 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1443,10 +1443,14 @@ class DeclContext { /// Has the full definition of this type been required by a use somewhere in /// the TU. uint64_t IsCompleteDefinitionRequired : 1; + +/// Whether this tag is a definition which was demoted due to +/// a module merge. +uint64_t IsThisDeclarationADemotedDefinition : 1; }; /// Number of non-inherited bits in TagDeclBitfields. - enum { NumTagDeclBits = 9 }; + enum { NumTagDeclBits = 10 }; /// Stores the bits used by EnumDecl. /// If modified NumEnumDeclBit and the accessor diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 060a6d1ad5ed5..030da7f55fac4 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4301,6 +4301,7 @@ TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext , DeclContext *DC, setEmbeddedInDeclarator(false); setFreeStanding(false); setCompleteDefinitionRequired(false); + TagDeclBits.IsThisDeclarationADemotedDefinition = false; } SourceLocation TagDecl::getOuterLocStart() const { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 1ab26e58a4040..25d7e9e6a2e68 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -773,7 +773,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { } if (OldDef) { Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef)); - ED->setCompleteDefinition(false); + ED->demoteThisDefinitionToDeclaration(); Reader.mergeDefinitionVisibility(OldDef, ED); if (OldDef->getODRHash() != ED->getODRHash()) Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED); @@ -828,7 +828,7 @@ void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { } if (OldDef) { Reader.MergedDeclContexts.insert(std::make_pair(RD, OldDef)); - RD->setCompleteDefinition(false); + RD->demoteThisDefinitionToDeclaration(); Reader.mergeDefinitionVisibility(OldDef, RD); } else { OldDef = RD; ___ cfe-commits mailing list cfe-commits@lists.llvm.org
[clang] 7ad693a - [modules] Update visibility for merged ObjCProtocolDecl definitions.
Author: Volodymyr Sapsai Date: 2021-11-08T13:54:00-08:00 New Revision: 7ad693a322c1b6765f5d06559c2bd73cc3938aaf URL: https://github.com/llvm/llvm-project/commit/7ad693a322c1b6765f5d06559c2bd73cc3938aaf DIFF: https://github.com/llvm/llvm-project/commit/7ad693a322c1b6765f5d06559c2bd73cc3938aaf.diff LOG: [modules] Update visibility for merged ObjCProtocolDecl definitions. Merge definition visibility the same way we do for other decls. Without the fix the added test emits `-Wobjc-method-access` as it cannot find a visible protocol. Make this warning `-Werror` so the test would fail when protocol visibility regresses. rdar://83600696 Differential Revision: https://reviews.llvm.org/D111860 Added: clang/test/Modules/merge-objc-protocol-visibility.m Modified: clang/lib/Serialization/ASTReaderDecl.cpp Removed: diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 2a617a4fec116..3e4a2416a3cd4 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1250,6 +1250,13 @@ void ASTDeclReader::ReadObjCDefinitionData( void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D, struct ObjCProtocolDecl::DefinitionData &) { + struct ObjCProtocolDecl::DefinitionData = D->data(); + if (DD.Definition != NewDD.Definition) { +Reader.MergedDeclContexts.insert( +std::make_pair(NewDD.Definition, DD.Definition)); +Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition); + } + // FIXME: odr checking? } diff --git a/clang/test/Modules/merge-objc-protocol-visibility.m b/clang/test/Modules/merge-objc-protocol-visibility.m new file mode 100644 index 0..04cf60b7e997a --- /dev/null +++ b/clang/test/Modules/merge-objc-protocol-visibility.m @@ -0,0 +1,76 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -emit-llvm -o %t/test.bc -F%t/Frameworks %t/test.m -Werror=objc-method-access -DHIDDEN_FIRST=1 \ +// RUN:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache +// RUN: %clang_cc1 -emit-llvm -o %t/test.bc -F%t/Frameworks %t/test.m -Werror=objc-method-access -DHIDDEN_FIRST=0 \ +// RUN:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache + +// Test a case when Objective-C protocol is imported both as hidden and as visible. + +//--- Frameworks/Foundation.framework/Headers/Foundation.h +@interface NSObject +@end + +//--- Frameworks/Foundation.framework/Modules/module.modulemap +framework module Foundation { + header "Foundation.h" + export * +} + +//--- Frameworks/Common.framework/Headers/Common.h +#import +@protocol Testing; +@interface Common : NSObject +- (id)getProtocolObj; +@end + +//--- Frameworks/Common.framework/Modules/module.modulemap +framework module Common { + header "Common.h" + export * +} + +//--- Frameworks/Regular.framework/Headers/Regular.h +@protocol Testing +- (void)protocolMethod; +@end + +//--- Frameworks/Regular.framework/Modules/module.modulemap +framework module Regular { + header "Regular.h" + export * +} + +//--- Frameworks/RegularHider.framework/Headers/Visible.h +// Empty, file required to create a module. + +//--- Frameworks/RegularHider.framework/Headers/Hidden.h +@protocol Testing +- (void)protocolMethod; +@end + +//--- Frameworks/RegularHider.framework/Modules/module.modulemap +framework module RegularHider { + header "Visible.h" + export * + + explicit module Hidden { +header "Hidden.h" +export * + } +} + +//--- test.m +#import + +#if HIDDEN_FIRST +#import +#import +#else +#import +#import +#endif + +void test(Common *obj) { + [[obj getProtocolObj] protocolMethod]; +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 0a35cc4 - [clang][objc] Speed up populating the global method pool from modules.
Author: Volodymyr Sapsai Date: 2021-11-03T17:11:14-07:00 New Revision: 0a35cc40b881a35c6a7a748f5fdefac4cafc33ce URL: https://github.com/llvm/llvm-project/commit/0a35cc40b881a35c6a7a748f5fdefac4cafc33ce DIFF: https://github.com/llvm/llvm-project/commit/0a35cc40b881a35c6a7a748f5fdefac4cafc33ce.diff LOG: [clang][objc] Speed up populating the global method pool from modules. For each selector encountered in the source code, we need to load selectors from the imported modules and check that we are calling a selector with compatible types. At the moment, for each module we are storing methods declared in the headers belonging to this module and methods from the transitive closure of imported modules. When a module is imported by a few other modules, methods from the shared module are duplicated in each importer. As the result, we can end up with lots of identical methods that we try to add to the global method pool. Doing this duplicate work is useless and relatively expensive. Avoid processing duplicate methods by storing in each module only its own methods and not storing methods from dependencies. Collect methods from dependencies by walking the graph of module dependencies. The issue was discovered and reported by Richard Howell. He has done the hard work for this fix as he has investigated and provided a detailed explanation of the performance problem. Differential Revision: https://reviews.llvm.org/D110123 Added: clang/test/Modules/method_pool_transitive.m Modified: clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/Modules/lookup.m Removed: diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 0f180d821ed7f..07a0f00aa5357 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8151,13 +8151,16 @@ namespace serialization { if (Reader.DeserializationListener) Reader.DeserializationListener->SelectorRead(Data.ID, Sel); - InstanceMethods.append(Data.Instance.begin(), Data.Instance.end()); - FactoryMethods.append(Data.Factory.begin(), Data.Factory.end()); + // Append methods in the reverse order, so that later we can process them + // in the order they appear in the source code by iterating through + // the vector in the reverse order. + InstanceMethods.append(Data.Instance.rbegin(), Data.Instance.rend()); + FactoryMethods.append(Data.Factory.rbegin(), Data.Factory.rend()); InstanceBits = Data.InstanceBits; FactoryBits = Data.FactoryBits; InstanceHasMoreThanOneDecl = Data.InstanceHasMoreThanOneDecl; FactoryHasMoreThanOneDecl = Data.FactoryHasMoreThanOneDecl; - return true; + return false; } /// Retrieve the instance methods found by this visitor. @@ -8186,9 +8189,8 @@ namespace serialization { /// Add the given set of methods to the method list. static void addMethodsToPool(Sema , ArrayRef Methods, ObjCMethodList ) { - for (unsigned I = 0, N = Methods.size(); I != N; ++I) { -S.addMethodToGlobalList(, Methods[I]); - } + for (auto I = Methods.rbegin(), E = Methods.rend(); I != E; ++I) +S.addMethodToGlobalList(, *I); } void ASTReader::ReadMethodPool(Selector Sel) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 7c500f30e271e..3e0e5e9c8f752 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -3045,11 +3045,11 @@ class ASTMethodPoolTrait { unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts for (const ObjCMethodList *Method = Method; Method = Method->getNext()) - if (Method->getMethod()) + if (ShouldWriteMethodListNode(Method)) DataLen += 4; for (const ObjCMethodList *Method = Method; Method = Method->getNext()) - if (Method->getMethod()) + if (ShouldWriteMethodListNode(Method)) DataLen += 4; return emitULEBKeyDataLength(KeyLen, DataLen, Out); } @@ -3080,13 +3080,13 @@ class ASTMethodPoolTrait { unsigned NumInstanceMethods = 0; for (const ObjCMethodList *Method = Method; Method = Method->getNext()) - if (Method->getMethod()) + if (ShouldWriteMethodListNode(Method)) ++NumInstanceMethods; unsigned NumFactoryMethods = 0; for (const ObjCMethodList *Method = Method; Method = Method->getNext()) - if (Method->getMethod()) + if (ShouldWriteMethodListNode(Method)) ++NumFactoryMethods; unsigned InstanceBits = Methods.Instance.getBits(); @@ -3107,15 +3107,20 @@ class ASTMethodPoolTrait { LE.write(FullFactoryBits); for (const ObjCMethodList *Method = Method; Method = Method->getNext()) - if (Method->getMethod()) + if
[clang] 048d2c7 - [modules] Update visibility for merged ObjCInterfaceDecl definitions.
Author: Volodymyr Sapsai Date: 2021-10-21T15:06:39-07:00 New Revision: 048d2c76efcddf4265987914e30d3d4f49395496 URL: https://github.com/llvm/llvm-project/commit/048d2c76efcddf4265987914e30d3d4f49395496 DIFF: https://github.com/llvm/llvm-project/commit/048d2c76efcddf4265987914e30d3d4f49395496.diff LOG: [modules] Update visibility for merged ObjCInterfaceDecl definitions. We keep using the first encountered definition and need to take into account visibility from subsequent definitions. For example, if the first definition is hidden and the second is visible, we need to make the first one visible too. rdar://82263843 Differential Revision: https://reviews.llvm.org/D110453 Added: clang/test/Modules/merge-objc-interface-visibility.m Modified: clang/lib/Serialization/ASTReaderDecl.cpp Removed: diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 7aab708d00e4a..2a617a4fec116 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1181,6 +1181,7 @@ void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, if (DD.Definition != NewDD.Definition) { Reader.MergedDeclContexts.insert( std::make_pair(NewDD.Definition, DD.Definition)); +Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition); } // FIXME: odr checking? diff --git a/clang/test/Modules/merge-objc-interface-visibility.m b/clang/test/Modules/merge-objc-interface-visibility.m new file mode 100644 index 0..181a2c716c6b3 --- /dev/null +++ b/clang/test/Modules/merge-objc-interface-visibility.m @@ -0,0 +1,61 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -emit-llvm -o %t/test.bc -F%t/Frameworks %t/test.m -DHIDDEN_FIRST=1 \ +// RUN:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache +// RUN: %clang_cc1 -emit-llvm -o %t/test.bc -F%t/Frameworks %t/test.m -DHIDDEN_FIRST=0 \ +// RUN:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache + +// Test a case when Objective-C interface is imported both as hidden and as visible. + +//--- Frameworks/Foundation.framework/Headers/Foundation.h +@interface NSObject +@end + +//--- Frameworks/Foundation.framework/Modules/module.modulemap +framework module Foundation { + header "Foundation.h" + export * +} + +//--- Frameworks/Regular.framework/Headers/Regular.h +#import +@interface Regular : NSObject +@end + +//--- Frameworks/Regular.framework/Modules/module.modulemap +framework module Regular { + header "Regular.h" + export * +} + +//--- Frameworks/RegularHider.framework/Headers/Visible.h +// Empty, file required to create a module. + +//--- Frameworks/RegularHider.framework/Headers/Hidden.h +#import +@interface Regular : NSObject +@end + +//--- Frameworks/RegularHider.framework/Modules/module.modulemap +framework module RegularHider { + header "Visible.h" + export * + + explicit module Hidden { +header "Hidden.h" +export * + } +} + +//--- test.m + +#if HIDDEN_FIRST +#import +#import +#else +#import +#import +#endif + +@interface SubClass : Regular +@end ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] d9eca33 - [modules] Fix tracking ObjCInterfaceType decl when there are multiple definitions.
Author: Volodymyr Sapsai Date: 2021-10-21T12:08:06-07:00 New Revision: d9eca3320a4d8db11ad65229ef6f564d134fc894 URL: https://github.com/llvm/llvm-project/commit/d9eca3320a4d8db11ad65229ef6f564d134fc894 DIFF: https://github.com/llvm/llvm-project/commit/d9eca3320a4d8db11ad65229ef6f564d134fc894.diff LOG: [modules] Fix tracking ObjCInterfaceType decl when there are multiple definitions. With the old approach we were updating `ObjCInterfaceType.Decl` to the last encountered definition. But during loading modules `ASTDeclReader::VisitObjCInterfaceDecl` keeps the *first* encountered definition. So with multiple definitions imported there would be a disagreement between expected definition in `ObjCInterfaceType.Decl` and actual definition `ObjCInterfaceDecl::getDefinition` which can lead to incorrect diagnostic. Fix by not tracking definition in `ObjCInterfaceType` explicitly but by getting it from redeclaration chain. Partially reverted 919fc50034b44c48aae8b80283f253ec2ee17f45 keeping the modified test case as the correct behavior is achieved in a different way. Differential Revision: https://reviews.llvm.org/D110452 Added: Modified: clang/include/clang/AST/Type.h clang/lib/AST/DeclObjC.cpp clang/lib/AST/Type.cpp clang/lib/Sema/SemaLookup.cpp clang/test/Modules/decldef.mm clang/test/Modules/interface-diagnose-missing-import.m Removed: diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index f8c1fe91085f0..722add6cd8777 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -6016,10 +6016,9 @@ inline ObjCProtocolDecl **ObjCTypeParamType::getProtocolStorageImpl() { class ObjCInterfaceType : public ObjCObjectType { friend class ASTContext; // ASTContext creates these. friend class ASTReader; - friend class ObjCInterfaceDecl; template friend class serialization::AbstractTypeReader; - mutable ObjCInterfaceDecl *Decl; + ObjCInterfaceDecl *Decl; ObjCInterfaceType(const ObjCInterfaceDecl *D) : ObjCObjectType(Nonce_ObjCInterface), @@ -6027,7 +6026,7 @@ class ObjCInterfaceType : public ObjCObjectType { public: /// Get the declaration of this interface. - ObjCInterfaceDecl *getDecl() const { return Decl; } + ObjCInterfaceDecl *getDecl() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 64eefc245f04a..ba827a79c0225 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -603,10 +603,6 @@ void ObjCInterfaceDecl::allocateDefinitionData() { assert(!hasDefinition() && "ObjC class already has a definition"); Data.setPointer(new (getASTContext()) DefinitionData()); Data.getPointer()->Definition = this; - - // Make the type point at the definition, now that we have one. - if (TypeForDecl) -cast(TypeForDecl)->Decl = this; } void ObjCInterfaceDecl::startDefinition() { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e7cdf58839631..ead3944284aec 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -821,6 +821,13 @@ QualType ObjCObjectType::stripObjCKindOfTypeAndQuals( /*isKindOf=*/false); } +ObjCInterfaceDecl *ObjCInterfaceType::getDecl() const { + ObjCInterfaceDecl *Canon = Decl->getCanonicalDecl(); + if (ObjCInterfaceDecl *Def = Canon->getDefinition()) +return Def; + return Canon; +} + const ObjCObjectPointerType *ObjCObjectPointerType::stripObjCKindOfTypeAndQuals( const ASTContext ) const { if (!isKindOfType() && qual_empty()) diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e4e5f57745c61..05529d0556211 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -5323,11 +5323,8 @@ static NamedDecl *getDefinitionToImport(NamedDecl *D) { return FD->getDefinition(); if (TagDecl *TD = dyn_cast(D)) return TD->getDefinition(); - // The first definition for this ObjCInterfaceDecl might be in the TU - // and not associated with any module. Use the one we know to be complete - // and have just seen in a module. if (ObjCInterfaceDecl *ID = dyn_cast(D)) -return ID; +return ID->getDefinition(); if (ObjCProtocolDecl *PD = dyn_cast(D)) return PD->getDefinition(); if (TemplateDecl *TD = dyn_cast(D)) diff --git a/clang/test/Modules/decldef.mm b/clang/test/Modules/decldef.mm index e8f070b511591..02883dc1d31e7 100644 --- a/clang/test/Modules/decldef.mm +++ b/clang/test/Modules/decldef.mm @@ -1,10 +1,12 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_1 -DUSE_2 -DUSE_3 -DUSE_4 -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fobjc-arc -I %S/Inputs
[clang] c593126 - [modules] While merging ObjCInterfaceDecl definitions, merge them as decl contexts too.
Author: Volodymyr Sapsai Date: 2021-10-20T18:48:29-07:00 New Revision: c5931267db26d71351c634df06006d9c818ff158 URL: https://github.com/llvm/llvm-project/commit/c5931267db26d71351c634df06006d9c818ff158 DIFF: https://github.com/llvm/llvm-project/commit/c5931267db26d71351c634df06006d9c818ff158.diff LOG: [modules] While merging ObjCInterfaceDecl definitions, merge them as decl contexts too. While working on https://reviews.llvm.org/D110280 I've tried to merge decl contexts as it seems to be correct and matching our handling of decl contexts from different modules. It's not required for the fix in https://reviews.llvm.org/D110280 but it revealed a missing diagnostic, so separating this change into a separate commit. Renamed some variables to distinguish diagnostic like "declaration of 'x' does not match" for different cases. Differential Revision: https://reviews.llvm.org/D110287 Added: Modified: clang/lib/Serialization/ASTReaderDecl.cpp clang/test/Modules/odr_hash.mm Removed: diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index f2c2023cbf233..7aab708d00e4a 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1177,6 +1177,12 @@ void ASTDeclReader::ReadObjCDefinitionData( void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, struct ObjCInterfaceDecl::DefinitionData &) { + struct ObjCInterfaceDecl::DefinitionData = D->data(); + if (DD.Definition != NewDD.Definition) { +Reader.MergedDeclContexts.insert( +std::make_pair(NewDD.Definition, DD.Definition)); + } + // FIXME: odr checking? } diff --git a/clang/test/Modules/odr_hash.mm b/clang/test/Modules/odr_hash.mm index 86ddd16b94fb7..276bd58624eca 100644 --- a/clang/test/Modules/odr_hash.mm +++ b/clang/test/Modules/odr_hash.mm @@ -241,12 +241,12 @@ @interface Interface4 { @end @interface Interface5 { @public - T x; + T y; } @end @interface Interface6 { @public - T1 x; + T1 z; } @end #elif defined(SECOND) @@ -257,14 +257,21 @@ @interface Interface4 { @end @interface Interface5 { @public - T x; + T y; } @end @interface Interface6 { @public - T2 x; + T2 z; } @end +#else +// expected-error@first.h:* {{'Interface4::x' from module 'FirstModule' is not present in definition of 'Interface4' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'x' does not match}} +// expected-error@first.h:* {{'Interface5::y' from module 'FirstModule' is not present in definition of 'Interface5' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'y' does not match}} +// expected-error@first.h:* {{'Interface6::z' from module 'FirstModule' is not present in definition of 'Interface6' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'z' does not match}} #endif namespace Types { @@ -276,22 +283,22 @@ @interface Interface6 { }; struct Invalid2 { Interface5 *I; - decltype(I->x) x; + decltype(I->y) y; }; struct Invalid3 { Interface6 *I; - decltype(I->x) x; + decltype(I->z) z; }; #else Invalid1 i1; // expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid1' in module 'SecondModule'}} // expected-note@second.h:* {{declaration of 'x' does not match}} Invalid2 i2; -// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid2::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid2' in module 'SecondModule'}} -// expected-note@second.h:* {{declaration of 'x' does not match}} +// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid2::y' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid2' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'y' does not match}} Invalid3 i3; -// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid3' in module 'SecondModule'}} -// expected-note@second.h:* {{declaration of 'x' does not match}} +// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid3::z' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid3' in module 'SecondModule'}} +// expected-note@second.h:* {{declaration of 'z' does not match}} #endif } // namespace ObjCTypeParam ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 91e19f6 - [driver] Explicitly specify `-fbuild-session-timestamp` in seconds.
Author: Volodymyr Sapsai Date: 2021-10-19T13:30:26-07:00 New Revision: 91e19f66e51ac3fda2309f5e67b02fcccd4d58a0 URL: https://github.com/llvm/llvm-project/commit/91e19f66e51ac3fda2309f5e67b02fcccd4d58a0 DIFF: https://github.com/llvm/llvm-project/commit/91e19f66e51ac3fda2309f5e67b02fcccd4d58a0.diff LOG: [driver] Explicitly specify `-fbuild-session-timestamp` in seconds. Representation of the file's last modification time depends on the file system and isn't guaranteed to be in seconds. Cast to seconds explicitly and tighten the test case to check the magnitude of the calculated value, so we can catch passing milliseconds or nanoseconds. rdar://83915615 Differential Revision: https://reviews.llvm.org/D111205 Added: Modified: clang/lib/Driver/ToolChains/Clang.cpp clang/test/Driver/modules.m Removed: diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index b689301e9bb1..8dabfff64f80 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3573,11 +3573,11 @@ static void RenderModulesOptions(Compilation , const Driver , llvm::sys::fs::file_status Status; if (llvm::sys::fs::status(A->getValue(), Status)) D.Diag(diag::err_drv_no_such_file) << A->getValue(); -CmdArgs.push_back( -Args.MakeArgString("-fbuild-session-timestamp=" + - Twine((uint64_t)Status.getLastModificationTime() - .time_since_epoch() - .count(; +CmdArgs.push_back(Args.MakeArgString( +"-fbuild-session-timestamp=" + +Twine((uint64_t)std::chrono::duration_cast( + Status.getLastModificationTime().time_since_epoch()) + .count(; } if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) { diff --git a/clang/test/Driver/modules.m b/clang/test/Driver/modules.m index 73db4e7e0fcc..67140926f176 100644 --- a/clang/test/Driver/modules.m +++ b/clang/test/Driver/modules.m @@ -11,7 +11,7 @@ // RUN: %clang -fbuild-session-file=%t.build-session-file -### %s 2>&1 | FileCheck -check-prefix=TIMESTAMP_ONLY %s // RUN: %clang -fbuild-session-timestamp=1280703457 -### %s 2>&1 | FileCheck -check-prefix=TIMESTAMP_ONLY %s -// TIMESTAMP_ONLY: -fbuild-session-timestamp=128 +// TIMESTAMP_ONLY: -fbuild-session-timestamp=128{{([[:digit:]]{7})[^[:digit:]]}} // RUN: %clang -fbuild-session-file=%t.build-session-file -fbuild-session-timestamp=123 -### %s 2>&1 | FileCheck -check-prefix=CONFLICT %s // CONFLICT: error: invalid argument '-fbuild-session-file={{.*}}.build-session-file' not allowed with '-fbuild-session-timestamp' @@ -21,7 +21,7 @@ // MODULES_VALIDATE_ONCE: -fmodules-validate-once-per-build-session // RUN: %clang -fbuild-session-file=%t.build-session-file -fmodules-validate-once-per-build-session -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_ONCE_FILE %s -// MODULES_VALIDATE_ONCE_FILE: -fbuild-session-timestamp=128 +// MODULES_VALIDATE_ONCE_FILE: -fbuild-session-timestamp=128{{([[:digit:]]{7})[^[:digit:]]}} // MODULES_VALIDATE_ONCE_FILE: -fmodules-validate-once-per-build-session // RUN: %clang -fmodules-validate-once-per-build-session -### %s 2>&1 | FileCheck -check-prefix=MODULES_VALIDATE_ONCE_ERR %s ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] d0e7bdc - [modules] Make a module map referenced by a system map a system one too.
Author: Volodymyr Sapsai Date: 2021-10-15T12:46:51-07:00 New Revision: d0e7bdc208491fd5d4245878c1ec2962694e2baa URL: https://github.com/llvm/llvm-project/commit/d0e7bdc208491fd5d4245878c1ec2962694e2baa DIFF: https://github.com/llvm/llvm-project/commit/d0e7bdc208491fd5d4245878c1ec2962694e2baa.diff LOG: [modules] Make a module map referenced by a system map a system one too. Mimic the behavior of including headers where a system includer makes an includee a system header too. rdar://84049469 Differential Revision: https://reviews.llvm.org/D111476 Added: Modified: clang/lib/Lex/ModuleMap.cpp clang/test/Modules/fmodules-validate-once-per-build-session.c Removed: diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 53b824baba58b..08381d0422058 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -2173,7 +2173,7 @@ void ModuleMapParser::parseExternModuleDecl() { } if (auto File = SourceMgr.getFileManager().getFile(FileNameRef)) Map.parseModuleMapFile( -*File, /*IsSystem=*/false, +*File, IsSystem, Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd ? Directory : (*File)->getDir(), diff --git a/clang/test/Modules/fmodules-validate-once-per-build-session.c b/clang/test/Modules/fmodules-validate-once-per-build-session.c index 840545bb59fc9..0c97342a8d70a 100644 --- a/clang/test/Modules/fmodules-validate-once-per-build-session.c +++ b/clang/test/Modules/fmodules-validate-once-per-build-session.c @@ -1,4 +1,5 @@ #include "foo.h" +#include "bar.h" // Clear the module cache. // RUN: rm -rf %t @@ -9,51 +10,74 @@ // Create a module. We will use -I or -isystem to determine whether to treat // foo.h as a system header. // RUN: echo 'void meow(void);' > %t/Inputs/foo.h +// RUN: echo 'void woof(void);' > %t/Inputs/bar.h // RUN: echo 'module Foo { header "foo.h" }' > %t/Inputs/module.map +// RUN: echo 'extern module Bar "bar.modulemap"' >> %t/Inputs/module.map +// RUN: echo 'module Bar { header "bar.h" }' > %t/Inputs/bar.modulemap // === // Compile the module. // RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s // RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s // RUN: ls -R %t/modules-cache | grep Foo.pcm.timestamp +// RUN: ls -R %t/modules-cache | grep Bar.pcm.timestamp // RUN: ls -R %t/modules-cache-user | grep Foo.pcm.timestamp +// RUN: ls -R %t/modules-cache-user | grep Bar.pcm.timestamp // RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-before.pcm +// RUN: cp %t/modules-cache/Bar.pcm %t/modules-to-compare/Bar-before.pcm // RUN: cp %t/modules-cache-user/Foo.pcm %t/modules-to-compare/Foo-before-user.pcm +// RUN: cp %t/modules-cache-user/Bar.pcm %t/modules-to-compare/Bar-before-user.pcm // === // Use it, and make sure that we did not recompile it. // RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -fsyntax-only -isystem %t/Inputs -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s // RUN: %clang_cc1 -cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache-user -fsyntax-only -I %t/Inputs -fbuild-session-timestamp=139000 -fmodules-validate-once-per-build-session %s // RUN: ls -R %t/modules-cache | grep Foo.pcm.timestamp +// RUN: ls -R %t/modules-cache | grep Bar.pcm.timestamp // RUN: ls -R %t/modules-cache-user | grep Foo.pcm.timestamp +// RUN: ls -R %t/modules-cache-user | grep Bar.pcm.timestamp // RUN: cp %t/modules-cache/Foo.pcm %t/modules-to-compare/Foo-after.pcm +// RUN: cp %t/modules-cache/Bar.pcm %t/modules-to-compare/Bar-after.pcm // RUN: cp %t/modules-cache-user/Foo.pcm %t/modules-to-compare/Foo-after-user.pcm +// RUN: cp %t/modules-cache-user/Bar.pcm %t/modules-to-compare/Bar-after-user.pcm // RUN: diff %t/modules-to-compare/Foo-before.pcm %t/modules-to-compare/Foo-after.pcm +// RUN: diff %t/modules-to-compare/Bar-before.pcm %t/modules-to-compare/Bar-after.pcm // RUN: diff %t/modules-to-compare/Foo-before-user.pcm %t/modules-to-compare/Foo-after-user.pcm +// RUN: diff %t/modules-to-compare/Bar-before-user.pcm %t/modules-to-compare/Bar-after-user.pcm // === // Change the sources. // RUN: echo 'void meow2(void);' > %t/Inputs/foo.h +// RUN: echo 'module Bar { header "bar.h" export * }' > %t/Inputs/bar.modulemap // === -// Use the module, and make sure that we did not recompile it if foo.h is a -// system header,
[clang] 9fad9de - [modules] Fix IRGen assertion on accessing ObjC ivar inside a method.
Author: Volodymyr Sapsai Date: 2021-10-07T17:09:31-07:00 New Revision: 9fad9de5c0032898a481e06bf5f696ca50c804c1 URL: https://github.com/llvm/llvm-project/commit/9fad9de5c0032898a481e06bf5f696ca50c804c1 DIFF: https://github.com/llvm/llvm-project/commit/9fad9de5c0032898a481e06bf5f696ca50c804c1.diff LOG: [modules] Fix IRGen assertion on accessing ObjC ivar inside a method. When have ObjCInterfaceDecl with the same name in 2 different modules, hitting the assertion > Assertion failed: (Index < RL->getFieldCount() && "Ivar is not inside record > layout!"), > function lookupFieldBitOffset, file > llvm-project/clang/lib/AST/RecordLayoutBuilder.cpp, line 3434. on accessing an ivar inside a method. The assertion happens because ivar belongs to one module while its containing interface belongs to another module and then we fail to find the ivar inside the containing interface. We already keep a single ObjCInterfaceDecl definition in redecleration chain and in this case containing interface was correct. The issue is with ObjCIvarDecl. IVar decl for IRGen is taken from ObjCIvarRefExpr that is created in `Sema::BuildIvarRefExpr` using ivar decl returned from `Sema::LookupIvarInObjCMethod`. And ivar lookup returns a wrong decl because basically we take the first ObjCIvarDecl found in `ASTReader::FindExternalVisibleDeclsByName` (called by `DeclContext::lookup`). And in `ASTReader.Lookups` lookup table for a wrong module comes first because `ASTReader::finishPendingActions` processes `PendingUpdateRecords` in reverse order and the first encountered ObjCIvarDecl will end up the last in `ASTReader.Lookups`. Fix by merging ObjCIvarDecl from different modules correctly and by using a canonical one in IRGen. rdar://82854574 Differential Revision: https://reviews.llvm.org/D110280 Added: clang/test/Modules/merge-objc-interface.m Modified: clang/include/clang/AST/DeclObjC.h clang/lib/AST/RecordLayoutBuilder.cpp clang/lib/Serialization/ASTReaderDecl.cpp Removed: diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 6bb9cdf67034d..f484dfedbf544 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -1955,6 +1955,13 @@ class ObjCIvarDecl : public FieldDecl { const ObjCIvarDecl *getNextIvar() const { return NextIvar; } void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; } + ObjCIvarDecl *getCanonicalDecl() override { +return cast(FieldDecl::getCanonicalDecl()); + } + const ObjCIvarDecl *getCanonicalDecl() const { +return const_cast(this)->getCanonicalDecl(); + } + void setAccessControl(AccessControl ac) { DeclAccess = ac; } AccessControl getAccessControl() const { return AccessControl(DeclAccess); } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index d49b0aec42fec..d17d1e26742c2 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -3404,6 +3404,7 @@ uint64_t ASTContext::getFieldOffset(const ValueDecl *VD) const { uint64_t ASTContext::lookupFieldBitOffset(const ObjCInterfaceDecl *OID, const ObjCImplementationDecl *ID, const ObjCIvarDecl *Ivar) const { + Ivar = Ivar->getCanonicalDecl(); const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); // FIXME: We should eliminate the need to have ObjCImplementationDecl passed diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d011d14612d13..f2c2023cbf233 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3350,6 +3350,9 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader , return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() : nullptr; + if (auto *OID = dyn_cast(DC)) +return OID->getDefinition(); + // We can see the TU here only if we have no Sema object. In that case, // there's no TU scope to look in, so using the DC alone is sufficient. if (auto *TU = dyn_cast(DC)) diff --git a/clang/test/Modules/merge-objc-interface.m b/clang/test/Modules/merge-objc-interface.m new file mode 100644 index 0..fba06294a26af --- /dev/null +++ b/clang/test/Modules/merge-objc-interface.m @@ -0,0 +1,105 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -emit-llvm -o %t/test.bc -F%t/Frameworks %t/test.m \ +// RUN:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache +// RUN: %clang_cc1 -emit-llvm -o %t/test.bc -F%t/Frameworks %t/test-functions.m \ +// RUN:-fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache + +// Test a case when Objective-C interface ivars are present in
[clang] 64ebf31 - [HeaderSearch] Use `isImport` only for imported headers and not for `#pragma once`.
Author: Volodymyr Sapsai Date: 2021-09-01T17:07:35-07:00 New Revision: 64ebf313a7e485e1a90da9cd69c412e06615a9bc URL: https://github.com/llvm/llvm-project/commit/64ebf313a7e485e1a90da9cd69c412e06615a9bc DIFF: https://github.com/llvm/llvm-project/commit/64ebf313a7e485e1a90da9cd69c412e06615a9bc.diff LOG: [HeaderSearch] Use `isImport` only for imported headers and not for `#pragma once`. There is a separate field `isPragmaOnce` and when `isImport` combines both, it complicates HeaderFileInfo serialization as `#pragma once` is the inherent property of the header while `isImport` reflects how other headers use it. The usage of the header can be different in different contexts, that's why `isImport` requires tracking separate from `#pragma once`. Differential Revision: https://reviews.llvm.org/D104351 Added: Modified: clang/include/clang/Lex/HeaderSearch.h clang/lib/Lex/HeaderSearch.cpp Removed: diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index a35a394f719b0..7df1127f42735 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -51,7 +51,7 @@ class TargetInfo; /// The preprocessor keeps track of this information for each /// file that is \#included. struct HeaderFileInfo { - /// True if this is a \#import'd or \#pragma once file. + /// True if this is a \#import'd file. unsigned isImport : 1; /// True if this is a \#pragma once file. @@ -450,11 +450,10 @@ class HeaderSearch { return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo; } - /// Mark the specified file as a "once only" file, e.g. due to + /// Mark the specified file as a "once only" file due to /// \#pragma once. void MarkFileIncludeOnce(const FileEntry *File) { HeaderFileInfo = getFileInfo(File); -FI.isImport = true; FI.isPragmaOnce = true; } @@ -500,8 +499,7 @@ class HeaderSearch { /// This routine does not consider the effect of \#import bool isFileMultipleIncludeGuarded(const FileEntry *File); - /// Determine whether the given file is known to have ever been \#imported - /// (or if it has been \#included and we've encountered a \#pragma once). + /// Determine whether the given file is known to have ever been \#imported. bool hasFileBeenImported(const FileEntry *File) { const HeaderFileInfo *FI = getExistingFileInfo(File); return FI && FI->isImport; diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index d5adbcf62cbc5..8bf61a2ba5972 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -91,7 +91,7 @@ void HeaderSearch::PrintStats() { << FileInfo.size() << " files tracked.\n"; unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0; for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) { -NumOnceOnlyFiles += FileInfo[i].isImport; +NumOnceOnlyFiles += (FileInfo[i].isPragmaOnce || FileInfo[i].isImport); if (MaxNumIncludes < FileInfo[i].NumIncludes) MaxNumIncludes = FileInfo[i].NumIncludes; NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1; @@ -1325,7 +1325,7 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor , } else { // Otherwise, if this is a #include of a file that was previously #import'd // or if this is the second #include of a #pragma once file, ignore it. -if (FileInfo.isImport && !TryEnterImported()) +if ((FileInfo.isPragmaOnce || FileInfo.isImport) && !TryEnterImported()) return false; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 93764ff - [modules] Fix miscompilation when using two RecordDecl definitions with the same name.
Author: Volodymyr Sapsai Date: 2021-08-30T17:51:38-07:00 New Revision: 93764ff6e2005b92057cffa9b3866307e2de260f URL: https://github.com/llvm/llvm-project/commit/93764ff6e2005b92057cffa9b3866307e2de260f DIFF: https://github.com/llvm/llvm-project/commit/93764ff6e2005b92057cffa9b3866307e2de260f.diff LOG: [modules] Fix miscompilation when using two RecordDecl definitions with the same name. When deserializing a RecordDecl we don't enforce that redeclaration chain contains only a single definition. So if the canonical decl is not a definition itself, `RecordType::getDecl` can return different objects before and after an include. It means we can build CGRecordLayout for one RecordDecl with its set of FieldDecl but try to use it with FieldDecl belonging to a different RecordDecl. With assertions enabled it results in > Assertion failed: (FieldInfo.count(FD) && "Invalid field for record!"), > function getLLVMFieldNo, file > llvm-project/clang/lib/CodeGen/CGRecordLayout.h, line 199. and with assertions disabled a bunch of fields are treated as their memory is located at offset 0. Fix by keeping the first encountered RecordDecl definition and marking the subsequent ones as non-definitions. Also need to merge FieldDecl properly, so that `getPrimaryMergedDecl` works correctly and during name lookup we don't treat fields from same-name RecordDecl as ambiguous. rdar://80184238 Differential Revision: https://reviews.llvm.org/D106994 Added: clang/test/Modules/Inputs/merge-record-definition/RecordDef.framework/Headers/RecordDef.h clang/test/Modules/Inputs/merge-record-definition/RecordDef.framework/Modules/module.modulemap clang/test/Modules/Inputs/merge-record-definition/RecordDefCopy.framework/Headers/RecordDefCopy.h clang/test/Modules/Inputs/merge-record-definition/RecordDefCopy.framework/Modules/module.modulemap clang/test/Modules/Inputs/merge-record-definition/RecordDefHidden.framework/Headers/Hidden.h clang/test/Modules/Inputs/merge-record-definition/RecordDefHidden.framework/Headers/Visible.h clang/test/Modules/Inputs/merge-record-definition/RecordDefHidden.framework/Modules/module.modulemap clang/test/Modules/Inputs/merge-record-definition/RecordDefIncluder.framework/Headers/RecordDefIncluder.h clang/test/Modules/Inputs/merge-record-definition/RecordDefIncluder.framework/Modules/module.modulemap clang/test/Modules/merge-record-definition-nonmodular.m clang/test/Modules/merge-record-definition-visibility.m clang/test/Modules/merge-record-definition.m Modified: clang/include/clang/Serialization/ASTReader.h clang/lib/Serialization/ASTCommon.cpp clang/lib/Serialization/ASTReaderDecl.cpp Removed: diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index e342a061379eb..f24ccf579aa8f 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1162,6 +1162,10 @@ class ASTReader /// definitions. Only populated when using modules in C++. llvm::DenseMap EnumDefinitions; + /// A mapping from canonical declarations of records to their canonical + /// definitions. Doesn't cover CXXRecordDecl. + llvm::DenseMap RecordDefinitions; + /// When reading a Stmt tree, Stmt operands are placed in this stack. SmallVector StmtStack; diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index 5fe1f96327ddc..db118d8b00776 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -474,7 +474,7 @@ bool serialization::needsAnonymousDeclarationNumber(const NamedDecl *D) { // Otherwise, we only care about anonymous class members / block-scope decls. // FIXME: We need to handle lambdas and blocks within inline / templated // variables too. - if (D->getDeclName() || !isa(D->getLexicalDeclContext())) + if (D->getDeclName() || !isa(D->getLexicalDeclContext())) return false; return isa(D) || isa(D); } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index ff79f91e5db1b..ef7921212f21b 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -332,7 +332,7 @@ namespace clang { RedeclarableResult VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD); -void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); } +void VisitRecordDecl(RecordDecl *RD); RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D); void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); } RedeclarableResult VisitClassTemplateSpecializationDeclImpl( @@ -808,6 +808,34 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { return Redecl; } +void
[clang] a4a5c00 - [Modules] Change result of reading AST block to llvm::Error instead
Author: Ben Barham Date: 2021-08-27T20:16:20-07:00 New Revision: a4a5c00b53d0638e2bd9011fa5cce7ef9739eea6 URL: https://github.com/llvm/llvm-project/commit/a4a5c00b53d0638e2bd9011fa5cce7ef9739eea6 DIFF: https://github.com/llvm/llvm-project/commit/a4a5c00b53d0638e2bd9011fa5cce7ef9739eea6.diff LOG: [Modules] Change result of reading AST block to llvm::Error instead Reading the AST block can never fail with a recoverable error as modules cannot be removed during this phase. Change the return type of these functions to return an llvm::Error instead, ie. either success or failure. NFC other than the wording of some of the errors. Differential Revision: https://reviews.llvm.org/D108268 Added: Modified: clang/include/clang/Serialization/ASTReader.h clang/lib/Serialization/ASTReader.cpp Removed: diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 242b75baca6c9..e342a061379eb 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1320,18 +1320,18 @@ class ASTReader ASTReaderListener *Listener, bool ValidateDiagnosticOptions); - ASTReadResult ReadASTBlock(ModuleFile , unsigned ClientLoadCapabilities); - ASTReadResult ReadExtensionBlock(ModuleFile ); + llvm::Error ReadASTBlock(ModuleFile , unsigned ClientLoadCapabilities); + llvm::Error ReadExtensionBlock(ModuleFile ); void ReadModuleOffsetMap(ModuleFile ) const; - bool ParseLineTable(ModuleFile , const RecordData ); - bool ReadSourceManagerBlock(ModuleFile ); + void ParseLineTable(ModuleFile , const RecordData ); + llvm::Error ReadSourceManagerBlock(ModuleFile ); llvm::BitstreamCursor (int ID); SourceLocation getImportLocation(ModuleFile *F); ASTReadResult ReadModuleMapFileBlock(RecordData , ModuleFile , const ModuleFile *ImportedBy, unsigned ClientLoadCapabilities); - ASTReadResult ReadSubmoduleBlock(ModuleFile , - unsigned ClientLoadCapabilities); + llvm::Error ReadSubmoduleBlock(ModuleFile , + unsigned ClientLoadCapabilities); static bool ParseLanguageOptions(const RecordData , bool Complain, ASTReaderListener , bool AllowCompatibleDifferences); @@ -1904,8 +1904,9 @@ class ASTReader /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the /// specified cursor. Read the abbreviations that are at the top of the block /// and then leave the cursor pointing into the block. - static bool ReadBlockAbbrevs(llvm::BitstreamCursor , unsigned BlockID, - uint64_t *StartOfBlockOffset = nullptr); + static llvm::Error ReadBlockAbbrevs(llvm::BitstreamCursor , + unsigned BlockID, + uint64_t *StartOfBlockOffset = nullptr); /// Finds all the visible declarations with a given name. /// The current implementation of this method just loads the entire diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 376dbdf1bd557..128350ce9ff8f 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -10,15 +10,13 @@ // //===--===// -#include "clang/Basic/OpenMPKinds.h" -#include "clang/Serialization/ASTRecordReader.h" #include "ASTCommon.h" #include "ASTReaderInternals.h" -#include "clang/AST/AbstractTypeReader.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/ASTUnresolvedSet.h" +#include "clang/AST/AbstractTypeReader.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -31,8 +29,8 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/OpenMPClause.h" #include "clang/AST/ODRHash.h" +#include "clang/AST/OpenMPClause.h" #include "clang/AST/RawCommentList.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" @@ -42,6 +40,7 @@ #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/CommentOptions.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticError.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/FileManager.h" @@ -51,6 +50,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/OperatorKinds.h"
[clang] 3220855 - [Modules] Do not remove failed modules after the control block phase
Author: Ben Barham Date: 2021-08-17T16:46:51-07:00 New Revision: 32208555af26c48f3df845a10b049c8eb74e2eb3 URL: https://github.com/llvm/llvm-project/commit/32208555af26c48f3df845a10b049c8eb74e2eb3 DIFF: https://github.com/llvm/llvm-project/commit/32208555af26c48f3df845a10b049c8eb74e2eb3.diff LOG: [Modules] Do not remove failed modules after the control block phase Reading modules first reads each control block in the chain and then all AST blocks. The first phase is intended to find recoverable errors, eg. an out of date or missing module. If any error occurs during this phase, it is safe to remove all modules in the chain as no references to them will exist. While reading the AST blocks, however, various fields in ASTReader are updated with references to the module. Removing modules at this point can cause dangling pointers which can be accessed later. These would be otherwise harmless, eg. a binary search over `GlobalSLocEntryMap` may access a failed module that could error, but shouldn't crash. Do not remove modules in this phase, regardless of failures. Since this is the case, it also doesn't make sense to return OutOfDate during this phase, so remove the two cases where this happens. When they were originally added these checks would return a failure when the serialized and current path didn't match up. That was updated to an OutOfDate as it was found to be hit when using VFS and overriding the umbrella. Later on the path was changed to instead be the name as written in the module file, resolved using the serialized base directory. At this point the check is really only comparing the name of the umbrella and only works for frameworks since those don't include `Headers/` in the name (which means the resolved path will never exist) Given all that, it seems safe to ignore this case entirely for now. This makes the handling of an umbrella header/directory the same as regular headers, which also don't check for differences in the path caused by VFS. Resolves rdar://79329355 Differential Revision: https://reviews.llvm.org/D107690 Added: clang/test/VFS/module-header-mismatches.m Modified: clang/lib/Serialization/ASTReader.cpp Removed: clang/test/VFS/Inputs/UsesFoo.framework/Headers/UsesFoo.h clang/test/VFS/Inputs/UsesFoo.framework/Modules/module.modulemap clang/test/VFS/umbrella-mismatch.m diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 83bade9941b3d..b8c4889b10f9d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -4240,8 +4240,11 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, PreviousGeneration = incrementGeneration(*ContextObj); unsigned NumModules = ModuleMgr.size(); - auto removeModulesAndReturn = [&](ASTReadResult ReadResult) { -assert(ReadResult && "expected to return error"); + SmallVector Loaded; + if (ASTReadResult ReadResult = + ReadASTCore(FileName, Type, ImportLoc, + /*ImportedBy=*/nullptr, Loaded, 0, 0, ASTFileSignature(), + ClientLoadCapabilities)) { ModuleMgr.removeModules(ModuleMgr.begin() + NumModules, PP.getLangOpts().Modules ? ().getModuleMap() @@ -4252,22 +4255,6 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, GlobalIndex.reset(); ModuleMgr.setGlobalIndex(nullptr); return ReadResult; - }; - - SmallVector Loaded; - switch (ASTReadResult ReadResult = - ReadASTCore(FileName, Type, ImportLoc, - /*ImportedBy=*/nullptr, Loaded, 0, 0, - ASTFileSignature(), ClientLoadCapabilities)) { - case Failure: - case Missing: - case OutOfDate: - case VersionMismatch: - case ConfigurationMismatch: - case HadErrors: -return removeModulesAndReturn(ReadResult); - case Success: -break; } // Here comes stuff that we only do once the entire chain is loaded. @@ -4279,18 +4266,18 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, // Read the AST block. if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities)) - return removeModulesAndReturn(Result); + return Failure; // The AST block should always have a definition for the main module. if (F.isModule() && !F.DidReadTopLevelSubmodule) { Error(diag::err_module_file_missing_top_level_submodule, F.FileName); - return removeModulesAndReturn(Failure); + return Failure; } // Read the extension blocks. while (!SkipCursorToBlock(F.Stream, EXTENSION_BLOCK_ID)) { if (ASTReadResult Result = ReadExtensionBlock(F)) -return removeModulesAndReturn(Result); +return Failure; } // Once read, set the ModuleFile bit base offset and update the size in @@ -5605,17
[clang] 766a08d - [Frontend] Only compile modules if not already finalized
Author: Ben Barham Date: 2021-07-15T18:27:08-07:00 New Revision: 766a08df12c111b15ed51d0fcac06042d2f68cd6 URL: https://github.com/llvm/llvm-project/commit/766a08df12c111b15ed51d0fcac06042d2f68cd6 DIFF: https://github.com/llvm/llvm-project/commit/766a08df12c111b15ed51d0fcac06042d2f68cd6.diff LOG: [Frontend] Only compile modules if not already finalized It was possible to re-add a module to a shared in-memory module cache when search paths are changed. This can eventually cause a crash if the original module is referenced after this occurs. 1. Module A depends on B 2. B exists in two paths C and D 3. First run only has C on the search path, finds A and B and loads them 4. Second run adds D to the front of the search path. A is loaded and contains a reference to the already compiled module from C. But searching finds the module from D instead, causing a mismatch 5. B and the modules that depend on it are considered out of date and thus rebuilt 6. The recompiled module A is added to the in-memory cache, freeing the previously inserted one This can never occur from a regular clang process, but is very easy to do through the API - whether through the use of a shared case or just running multiple compilations from a single `CompilerInstance`. Update the compilation to return early if a module is already finalized so that the pre-condition in the in-memory module cache holds. Resolves rdar://78180255 Differential Revision: https://reviews.llvm.org/D105328 Added: clang/unittests/Serialization/ModuleCacheTest.cpp Modified: clang/include/clang/Basic/DiagnosticCommonKinds.td clang/include/clang/Basic/DiagnosticSerializationKinds.td clang/include/clang/Serialization/ASTReader.h clang/lib/Frontend/CompilerInstance.cpp clang/lib/Serialization/ASTReader.cpp clang/unittests/Serialization/CMakeLists.txt Removed: diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index eea5d8eaa10a1..4dff3379ed35b 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -111,6 +111,8 @@ def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, DefaultFatal; def err_module_prebuilt : Error< "error in loading module '%0' from prebuilt module path">, DefaultFatal; +def err_module_rebuild_finalized : Error< + "cannot rebuild module '%0' as it is already finalized">, DefaultFatal; def note_pragma_entered_here : Note<"#pragma entered here">; def note_decl_hiding_tag_type : Note< "%1 %0 is hidden by a non-type declaration of %0 here">; diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index ce48833a87030..bf3221be004de 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -69,6 +69,9 @@ def err_module_file_not_module : Error< "AST file '%0' was not built as a module">, DefaultFatal; def err_module_file_missing_top_level_submodule : Error< "module file '%0' is missing its top-level submodule">, DefaultFatal; +def note_module_file_conflict : Note< + "this is generally caused by modules with the same name found in multiple " + "paths">; def remark_module_import : Remark< "importing module '%0'%select{| into '%3'}2 from '%1'">, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 6932d9c86d0cc..4819a5aecefaf 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1401,6 +1401,9 @@ class ASTReader llvm::iterator_range getModulePreprocessedEntities(ModuleFile ) const; + bool canRecoverFromOutOfDate(StringRef ModuleFileName, + unsigned ClientLoadCapabilities); + public: class ModuleDeclIterator : public llvm::iterator_adaptor_base< diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index a6e2329c8864a..c642af1849bc4 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1054,6 +1054,15 @@ compileModuleImpl(CompilerInstance , SourceLocation ImportLoc, [](CompilerInstance &) {}) { llvm::TimeTraceScope TimeScope("Module Compile", ModuleName); + // Never compile a module that's already finalized - this would cause the + // existing module to be freed, causing crashes if it is later referenced + if (ImportingInstance.getModuleCache().isPCMFinal(ModuleFileName)) { +ImportingInstance.getDiagnostics().Report( +ImportLoc, diag::err_module_rebuild_finalized) +<< ModuleName; +return false; + } + // Construct a compiler invocation for creating
[clang] 722c514 - [clang][AST] Make `getLocalOrImportedSubmoduleID` work with const `Module*`. NFC.
Author: Volodymyr Sapsai Date: 2021-06-17T17:29:12-07:00 New Revision: 722c51473c7a3bfe13d929734615a3b46d44c09a URL: https://github.com/llvm/llvm-project/commit/722c51473c7a3bfe13d929734615a3b46d44c09a DIFF: https://github.com/llvm/llvm-project/commit/722c51473c7a3bfe13d929734615a3b46d44c09a.diff LOG: [clang][AST] Make `getLocalOrImportedSubmoduleID` work with const `Module*`. NFC. Differential Revision: https://reviews.llvm.org/D104350 Added: Modified: clang/include/clang/Serialization/ASTWriter.h clang/lib/Serialization/ASTWriter.cpp Removed: diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index a7a659637902e..e4d92f0b0515c 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -450,7 +450,7 @@ class ASTWriter : public ASTDeserializationListener, /// A mapping from each known submodule to its ID number, which will /// be a positive integer. - llvm::DenseMap SubmoduleIDs; + llvm::DenseMap SubmoduleIDs; /// A list of the module file extension writers. std::vector> @@ -671,7 +671,7 @@ class ASTWriter : public ASTDeserializationListener, /// Retrieve or create a submodule ID for this module, or return 0 if /// the submodule is neither local (a submodle of the currently-written module) /// nor from an imported module. - unsigned getLocalOrImportedSubmoduleID(Module *Mod); + unsigned getLocalOrImportedSubmoduleID(const Module *Mod); /// Note that the identifier II occurs at the given offset /// within the identifier table. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 4cdcf53775de1..ca169c010555c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -2476,11 +2476,11 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord , } } -unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) { +unsigned ASTWriter::getLocalOrImportedSubmoduleID(const Module *Mod) { if (!Mod) return 0; - llvm::DenseMap::iterator Known = SubmoduleIDs.find(Mod); + auto Known = SubmoduleIDs.find(Mod); if (Known != SubmoduleIDs.end()) return Known->second; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits