Vendor import of clang trunk r303291:

https://llvm.org/svn/llvm-project/cfe/trunk@303291
This commit is contained in:
Dimitry Andric 2017-05-17 20:22:49 +00:00
parent 2410013d93
commit 1ce0879276
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=318416
svn path=/vendor/clang/clang-trunk-r303291/; revision=318417; tag=vendor/clang/clang-trunk-r303291
27 changed files with 429 additions and 164 deletions

View File

@ -301,16 +301,6 @@ class NamedDecl : public Decl {
using Decl::isModulePrivate;
using Decl::setModulePrivate;
/// \brief Determine whether this declaration is hidden from name lookup.
bool isHidden() const { return Hidden; }
/// \brief Set whether this declaration is hidden from name lookup.
void setHidden(bool Hide) {
assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) &&
"declaration with no owning module can't be hidden");
Hidden = Hide;
}
/// \brief Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
const DeclContext *DC = getDeclContext();

View File

@ -706,6 +706,20 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
reinterpret_cast<Module **>(this)[-1] = M;
}
Module *getOwningModule() const {
return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule();
}
/// \brief Determine whether this declaration is hidden from name lookup.
bool isHidden() const { return Hidden; }
/// \brief Set whether this declaration is hidden from name lookup.
void setHidden(bool Hide) {
assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) &&
"declaration with no owning module can't be hidden");
Hidden = Hide;
}
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}

View File

@ -166,6 +166,11 @@ class LangOptions : public LangOptionsBase {
return getCompilingModule() != CMK_None;
}
/// Do we need to track the owning module for a local declaration?
bool trackLocalOwningModule() const {
return ModulesLocalVisibility;
}
bool isSignedOverflowDefined() const {
return getSignedOverflowBehavior() == SOB_Defined;
}

View File

@ -865,7 +865,7 @@ class SourceManager : public RefCountedBase<SourceManager> {
const FileEntry *NewFile);
/// \brief Returns true if the file contents have been overridden.
bool isFileOverridden(const FileEntry *File) {
bool isFileOverridden(const FileEntry *File) const {
if (OverriddenFilesInfo) {
if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File))
return true;

View File

@ -419,7 +419,6 @@ class ASTUnit : public ModuleLoader {
explicit ASTUnit(bool MainFileIsAST);
void CleanTemporaryFiles();
bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer);
@ -530,11 +529,6 @@ class ASTUnit : public ModuleLoader {
ASTMutationListener *getASTMutationListener();
ASTDeserializationListener *getDeserializationListener();
/// \brief Add a temporary file that the ASTUnit depends on.
///
/// This file will be erased when the ASTUnit is destroyed.
void addTemporaryFile(StringRef TempFile);
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; }

View File

@ -1467,11 +1467,9 @@ class Sema {
VisibleModuleSet VisibleModules;
Module *CachedFakeTopLevelModule;
public:
/// \brief Get the module owning an entity.
Module *getOwningModule(Decl *Entity);
Module *getOwningModule(Decl *Entity) { return Entity->getOwningModule(); }
/// \brief Make a merged definition of an existing hidden definition \p ND
/// visible at the specified location.

View File

@ -1038,10 +1038,10 @@ void ASTDumper::dumpDecl(const Decl *D) {
dumpSourceRange(D->getSourceRange());
OS << ' ';
dumpLocation(D->getLocation());
if (Module *M = D->getImportedOwningModule())
if (D->isFromASTFile())
OS << " imported";
if (Module *M = D->getOwningModule())
OS << " in " << M->getFullModuleName();
else if (Module *M = D->getLocalOwningModule())
OS << " in (local) " << M->getFullModuleName();
if (auto *ND = dyn_cast<NamedDecl>(D))
for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
const_cast<NamedDecl *>(ND)))

View File

@ -47,9 +47,7 @@ bool Decl::isOutOfLine() const {
TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, nullptr, SourceLocation()),
DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {
Hidden = Ctx.getLangOpts().ModulesLocalVisibility;
}
DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {}
//===----------------------------------------------------------------------===//
// NamedDecl Implementation

View File

@ -75,7 +75,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
assert(!Parent || &Parent->getParentASTContext() == &Ctx);
// With local visibility enabled, we track the owning module even for local
// declarations.
if (Ctx.getLangOpts().ModulesLocalVisibility) {
if (Ctx.getLangOpts().trackLocalOwningModule()) {
// Ensure required alignment of the resulting object by adding extra
// padding at the start if required.
size_t ExtraAlign =
@ -83,7 +83,9 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
char *Buffer = reinterpret_cast<char *>(
::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
Buffer += ExtraAlign;
return new (Buffer) Module*(nullptr) + 1;
auto *ParentModule =
Parent ? cast<Decl>(Parent)->getOwningModule() : nullptr;
return new (Buffer) Module*(ParentModule) + 1;
}
return ::operator new(Size + Extra, Ctx);
}
@ -94,7 +96,7 @@ Module *Decl::getOwningModuleSlow() const {
}
bool Decl::hasLocalOwningModuleStorage() const {
return getASTContext().getLangOpts().ModulesLocalVisibility;
return getASTContext().getLangOpts().trackLocalOwningModule();
}
const char *Decl::getDeclKindName() const {
@ -273,6 +275,8 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
getMultipleDC()->LexicalDC = DC;
}
Hidden = cast<Decl>(DC)->Hidden;
if (Hidden && !isFromASTFile() && hasLocalOwningModuleStorage())
setLocalOwningModule(cast<Decl>(DC)->getOwningModule());
}
void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,

View File

@ -81,7 +81,35 @@ void ODRHash::AddDeclarationName(DeclarationName Name) {
}
}
void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {}
void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
assert(NNS && "Expecting non-null pointer.");
const auto *Prefix = NNS->getPrefix();
AddBoolean(Prefix);
if (Prefix) {
AddNestedNameSpecifier(Prefix);
}
auto Kind = NNS->getKind();
ID.AddInteger(Kind);
switch (Kind) {
case NestedNameSpecifier::Identifier:
AddIdentifierInfo(NNS->getAsIdentifier());
break;
case NestedNameSpecifier::Namespace:
AddDecl(NNS->getAsNamespace());
break;
case NestedNameSpecifier::NamespaceAlias:
AddDecl(NNS->getAsNamespaceAlias());
break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
AddType(NNS->getAsType());
break;
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Super:
break;
}
}
void ODRHash::AddTemplateName(TemplateName Name) {}
void ODRHash::AddTemplateArgument(TemplateArgument TA) {}
void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {}
@ -335,6 +363,20 @@ class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
Hash.AddQualType(T);
}
void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
Hash.AddBoolean(NNS);
if (NNS) {
Hash.AddNestedNameSpecifier(NNS);
}
}
void AddIdentifierInfo(const IdentifierInfo *II) {
Hash.AddBoolean(II);
if (II) {
Hash.AddIdentifierInfo(II);
}
}
void VisitQualifiers(Qualifiers Quals) {
ID.AddInteger(Quals.getAsOpaqueValue());
}
@ -414,6 +456,42 @@ class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
AddQualType(T->getDecl()->getUnderlyingType().getCanonicalType());
VisitType(T);
}
void VisitTagType(const TagType *T) {
AddDecl(T->getDecl());
VisitType(T);
}
void VisitRecordType(const RecordType *T) { VisitTagType(T); }
void VisitEnumType(const EnumType *T) { VisitTagType(T); }
void VisitTypeWithKeyword(const TypeWithKeyword *T) {
ID.AddInteger(T->getKeyword());
VisitType(T);
};
void VisitDependentNameType(const DependentNameType *T) {
AddNestedNameSpecifier(T->getQualifier());
AddIdentifierInfo(T->getIdentifier());
VisitTypeWithKeyword(T);
}
void VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType *T) {
AddIdentifierInfo(T->getIdentifier());
AddNestedNameSpecifier(T->getQualifier());
ID.AddInteger(T->getNumArgs());
for (const auto &TA : T->template_arguments()) {
Hash.AddTemplateArgument(TA);
}
VisitTypeWithKeyword(T);
}
void VisitElaboratedType(const ElaboratedType *T) {
AddNestedNameSpecifier(T->getQualifier());
AddQualType(T->getNamedType());
VisitTypeWithKeyword(T);
}
};
void ODRHash::AddType(const Type *T) {

View File

@ -2860,7 +2860,7 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit,
if (DebugKind >= codegenoptions::LimitedDebugInfo) {
if (const NamespaceDecl *NSDecl =
dyn_cast_or_null<NamespaceDecl>(FD->getLexicalDeclContext()))
dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
FDContext = getOrCreateNamespace(NSDecl);
else if (const RecordDecl *RDecl =
dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) {

View File

@ -125,8 +125,15 @@ static bool findVCToolChainViaEnvironment(std::string &Path,
continue;
// whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
if (llvm::sys::path::filename(PathEntry) == "bin") {
llvm::StringRef ParentPath = llvm::sys::path::parent_path(PathEntry);
llvm::StringRef TestPath = PathEntry;
bool IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
if (!IsBin) {
// Strip any architecture subdir like "amd64".
TestPath = llvm::sys::path::parent_path(TestPath);
IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin");
}
if (IsBin) {
llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
if (llvm::sys::path::filename(ParentPath) == "VC") {
Path = ParentPath;
IsVS2017OrNewer = false;

View File

@ -84,13 +84,6 @@ namespace {
/// \brief The file in which the precompiled preamble is stored.
std::string PreambleFile;
/// \brief Temporary files that should be removed when the ASTUnit is
/// destroyed.
SmallVector<std::string, 4> TemporaryFiles;
/// \brief Erase temporary files.
void CleanTemporaryFiles();
/// \brief Erase the preamble file.
void CleanPreambleFile();
@ -163,12 +156,6 @@ static const std::string &getPreambleFile(const ASTUnit *AU) {
return getOnDiskData(AU).PreambleFile;
}
void OnDiskData::CleanTemporaryFiles() {
for (StringRef File : TemporaryFiles)
llvm::sys::fs::remove(File);
TemporaryFiles.clear();
}
void OnDiskData::CleanPreambleFile() {
if (!PreambleFile.empty()) {
llvm::sys::fs::remove(PreambleFile);
@ -177,7 +164,6 @@ void OnDiskData::CleanPreambleFile() {
}
void OnDiskData::Cleanup() {
CleanTemporaryFiles();
CleanPreambleFile();
}
@ -194,14 +180,6 @@ void ASTUnit::clearFileLevelDecls() {
llvm::DeleteContainerSeconds(FileDecls);
}
void ASTUnit::CleanTemporaryFiles() {
getOnDiskData(this).CleanTemporaryFiles();
}
void ASTUnit::addTemporaryFile(StringRef TempFile) {
getOnDiskData(this).TemporaryFiles.push_back(TempFile);
}
/// \brief After failing to build a precompiled preamble (due to
/// errors in the source that occurs in the preamble), the number of
/// reparses during which we'll skip even trying to precompile the
@ -1100,7 +1078,6 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
// Clear out old caches and data.
TopLevelDecls.clear();
clearFileLevelDecls();
CleanTemporaryFiles();
if (!OverrideMainBuffer) {
checkAndRemoveNonDriverDiags(StoredDiagnostics);

View File

@ -2133,7 +2133,7 @@ void _mm_sfence(void);
/// \headerfile <x86intrin.h>
///
/// \code
/// void _mm_extract_pi(__m64 a, int n);
/// int _mm_extract_pi16(__m64 a, int n);
/// \endcode
///
/// This intrinsic corresponds to the <c> VPEXTRW / PEXTRW </c> instruction.
@ -2157,7 +2157,7 @@ void _mm_sfence(void);
/// \headerfile <x86intrin.h>
///
/// \code
/// void _mm_insert_pi(__m64 a, int d, int n);
/// __m64 _mm_insert_pi16(__m64 a, int d, int n);
/// \endcode
///
/// This intrinsic corresponds to the <c> VPINSRW / PINSRW </c> instruction.
@ -2680,8 +2680,7 @@ _mm_movelh_ps(__m128 __a, __m128 __b)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
/// instruction.
/// This intrinsic corresponds to the <c> CVTPI2PS + COMPOSITE </c> instruction.
///
/// \param __a
/// A 64-bit vector of [4 x i16]. The elements of the destination are copied
@ -2711,8 +2710,7 @@ _mm_cvtpi16_ps(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
/// instruction.
/// This intrinsic corresponds to the <c> CVTPI2PS + COMPOSITE </c> instruction.
///
/// \param __a
/// A 64-bit vector of 16-bit unsigned integer values. The elements of the
@ -2741,8 +2739,7 @@ _mm_cvtpu16_ps(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
/// instruction.
/// This intrinsic corresponds to the <c> CVTPI2PS + COMPOSITE </c> instruction.
///
/// \param __a
/// A 64-bit vector of [8 x i8]. The elements of the destination are copied
@ -2766,8 +2763,7 @@ _mm_cvtpi8_ps(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
/// instruction.
/// This intrinsic corresponds to the <c> CVTPI2PS + COMPOSITE </c> instruction.
///
/// \param __a
/// A 64-bit vector of unsigned 8-bit integer values. The elements of the
@ -2791,8 +2787,7 @@ _mm_cvtpu8_ps(__m64 __a)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> CVTPI2PS + \c COMPOSITE </c>
/// instruction.
/// This intrinsic corresponds to the <c> CVTPI2PS + COMPOSITE </c> instruction.
///
/// \param __a
/// A 64-bit vector of [2 x i32]. The lower elements of the destination are
@ -2826,8 +2821,7 @@ _mm_cvtpi32x2_ps(__m64 __a, __m64 __b)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> CVTPS2PI + \c COMPOSITE </c>
/// instruction.
/// This intrinsic corresponds to the <c> CVTPS2PI + COMPOSITE </c> instruction.
///
/// \param __a
/// A 128-bit floating-point vector of [4 x float].
@ -2857,8 +2851,7 @@ _mm_cvtps_pi16(__m128 __a)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> CVTPS2PI + \c COMPOSITE </c>
/// instruction.
/// This intrinsic corresponds to the <c> CVTPS2PI + COMPOSITE </c> instruction.
///
/// \param __a
/// 128-bit floating-point vector of [4 x float].

View File

@ -43,6 +43,8 @@ using namespace clang;
/// isObjCAtKeyword - Return true if we have an ObjC keyword identifier.
bool Token::isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const {
if (isAnnotation())
return false;
if (IdentifierInfo *II = getIdentifierInfo())
return II->getObjCKeywordID() == objcKey;
return false;
@ -50,6 +52,8 @@ bool Token::isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const {
/// getObjCKeywordID - Return the ObjC keyword kind.
tok::ObjCKeywordKind Token::getObjCKeywordID() const {
if (isAnnotation())
return tok::objc_not_keyword;
IdentifierInfo *specId = getIdentifierInfo();
return specId ? specId->getObjCKeywordID() : tok::objc_not_keyword;
}

View File

@ -93,11 +93,10 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false),
TUKind(TUKind), NumSFINAEErrors(0), CachedFakeTopLevelModule(nullptr),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
TyposCorrected(0), AnalysisWarnings(*this),
TUKind(TUKind), NumSFINAEErrors(0), AccessCheckingSFINAE(false),
InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr),
DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
TUScope = nullptr;

View File

@ -16047,6 +16047,14 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) {
ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
VisibleModules.setVisible(Mod, DirectiveLoc);
// The enclosing context is now part of this module.
// FIXME: Consider creating a child DeclContext to hold the entities
// lexically within the module.
if (getLangOpts().trackLocalOwningModule()) {
cast<Decl>(CurContext)->setHidden(true);
cast<Decl>(CurContext)->setLocalOwningModule(Mod);
}
}
void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) {
@ -16075,6 +16083,13 @@ void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) {
DirectiveLoc = EomLoc;
}
BuildModuleInclude(DirectiveLoc, Mod);
// Any further declarations are in whatever module we returned to.
if (getLangOpts().trackLocalOwningModule()) {
cast<Decl>(CurContext)->setLocalOwningModule(getCurrentModule());
if (!getCurrentModule())
cast<Decl>(CurContext)->setHidden(false);
}
}
void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,

View File

@ -1326,62 +1326,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
return !R.empty();
}
Module *Sema::getOwningModule(Decl *Entity) {
// If it's imported, grab its owning module.
Module *M = Entity->getImportedOwningModule();
if (M || !isa<NamedDecl>(Entity) || !cast<NamedDecl>(Entity)->isHidden())
return M;
assert(!Entity->isFromASTFile() &&
"hidden entity from AST file has no owning module");
if (!getLangOpts().ModulesLocalVisibility) {
// If we're not tracking visibility locally, the only way a declaration
// can be hidden and local is if it's hidden because it's parent is (for
// instance, maybe this is a lazily-declared special member of an imported
// class).
auto *Parent = cast<NamedDecl>(Entity->getDeclContext());
assert(Parent->isHidden() && "unexpectedly hidden decl");
return getOwningModule(Parent);
}
// It's local and hidden; grab or compute its owning module.
M = Entity->getLocalOwningModule();
if (M)
return M;
if (auto *Containing =
PP.getModuleContainingLocation(Entity->getLocation())) {
M = Containing;
} else if (Entity->isInvalidDecl() || Entity->getLocation().isInvalid()) {
// Don't bother tracking visibility for invalid declarations with broken
// locations.
cast<NamedDecl>(Entity)->setHidden(false);
} else {
// We need to assign a module to an entity that exists outside of any
// module, so that we can hide it from modules that we textually enter.
// Invent a fake module for all such entities.
if (!CachedFakeTopLevelModule) {
CachedFakeTopLevelModule =
PP.getHeaderSearchInfo().getModuleMap().findOrCreateModule(
"<top-level>", nullptr, false, false).first;
auto &SrcMgr = PP.getSourceManager();
SourceLocation StartLoc =
SrcMgr.getLocForStartOfFile(SrcMgr.getMainFileID());
auto &TopLevel = ModuleScopes.empty()
? VisibleModules
: ModuleScopes[0].OuterVisibleModules;
TopLevel.setVisible(CachedFakeTopLevelModule, StartLoc);
}
M = CachedFakeTopLevelModule;
}
if (M)
Entity->setLocalOwningModule(M);
return M;
}
void Sema::makeMergedDefinitionVisible(NamedDecl *ND) {
if (auto *M = getCurrentModule())
Context.mergeDefinitionIntoModule(ND, M);
@ -1520,7 +1464,6 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
if (SemaRef.getLangOpts().ModulesLocalVisibility) {
DeclModule = SemaRef.getOwningModule(D);
if (!DeclModule) {
// getOwningModule() may have decided the declaration should not be hidden.
assert(!D->isHidden() && "hidden decl not from a module");
return true;
}

View File

@ -9348,12 +9348,6 @@ void ASTReader::diagnoseOdrViolations() {
return Hash.CalculateHash();
};
auto ComputeDeclNameODRHash = [&Hash](const DeclarationName Name) {
Hash.clear();
Hash.AddDeclarationName(Name);
return Hash.CalculateHash();
};
auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
Hash.clear();
Hash.AddQualType(Ty);
@ -9446,11 +9440,8 @@ void ASTReader::diagnoseOdrViolations() {
QualType FirstType = FirstField->getType();
QualType SecondType = SecondField->getType();
const TypedefType *FirstTypedef = dyn_cast<TypedefType>(FirstType);
const TypedefType *SecondTypedef = dyn_cast<TypedefType>(SecondType);
if ((FirstTypedef && !SecondTypedef) ||
(!FirstTypedef && SecondTypedef)) {
if (ComputeQualTypeODRHash(FirstType) !=
ComputeQualTypeODRHash(SecondType)) {
ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(),
FieldTypeName)
<< FirstII << FirstType;
@ -9462,24 +9453,6 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
if (FirstTypedef && SecondTypedef) {
unsigned FirstHash = ComputeDeclNameODRHash(
FirstTypedef->getDecl()->getDeclName());
unsigned SecondHash = ComputeDeclNameODRHash(
SecondTypedef->getDecl()->getDeclName());
if (FirstHash != SecondHash) {
ODRDiagError(FirstField->getLocation(),
FirstField->getSourceRange(), FieldTypeName)
<< FirstII << FirstType;
ODRDiagNote(SecondField->getLocation(),
SecondField->getSourceRange(), FieldTypeName)
<< SecondII << SecondType;
Diagnosed = true;
break;
}
}
const bool IsFirstBitField = FirstField->isBitField();
const bool IsSecondBitField = SecondField->isBitField();
if (IsFirstBitField != IsSecondBitField) {

View File

@ -60,6 +60,10 @@ void B::func_fwd() {
anonymous = 0;
}
namespace C {
void c();
}
void C::c() {}
// This should work even if 'i' and 'func' were declarations & not definitions,
// but it doesn't yet.
@ -114,6 +118,8 @@ void B::func_fwd() {
// CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]]
// CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 53,{{.*}} isDefinition: true
// CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]]
// CHECK: distinct !DISubprogram(name: "c",{{.*}}, scope: ![[C:[0-9]+]],{{.*}}, line: 60,{{.*}} isDefinition: true
// CHECK: ![[C]] = !DINamespace(name: "C",
// CHECK-GMLT: [[CU:![0-9]+]] = distinct !DICompileUnit(
// CHECK-GMLT-SAME: emissionKind: LineTablesOnly,

View File

@ -441,3 +441,7 @@ module DebugNestedB {
header "DebugNestedB.h"
export *
}
module objcAtKeywordMissingEnd {
header "objcAtKeywordMissingEnd.h"
}

View File

@ -0,0 +1,3 @@
@interface MissingEnd // expected-note {{class started here}}
@ // expected-error {{expected an Objective-C directive after '@'}} expected-error {{missing '@end'}}

View File

@ -4,7 +4,11 @@ int m = n;
#include "c.h"
#if defined(A) && !defined(ALLOW_NAME_LEAKAGE)
#error A is defined
#warning A is defined
#endif
#define B
template<typename T> void b_template() {
N::C::f(0);
}

View File

@ -1 +1,10 @@
#include "c.h"
#ifndef OTHER_H
#define OTHER_H
namespace N {
struct C {
template<typename U> static void f(U) {}
};
}
#endif

View File

@ -0,0 +1,7 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -verify -x objective-c -fmodule-name=objcAtKeywordMissingEnd -emit-module %S/Inputs/module.map
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c -fmodule-name=Empty -emit-module %S/Inputs/module.map
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -verify -I %S/Inputs %s
@interface X // expected-note {{class started here}}
#pragma clang module import Empty // expected-error {{missing '@end'}}

View File

@ -634,6 +634,237 @@ S3 s3;
#endif
} // namespace Using
namespace RecordType {
#if defined(FIRST)
struct B1 {};
struct S1 {
B1 x;
};
#elif defined(SECOND)
struct A1 {};
struct S1 {
A1 x;
};
#else
S1 s1;
// expected-error@first.h:* {{'RecordType::S1::x' from module 'FirstModule' is not present in definition of 'RecordType::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif
}
namespace DependentType {
#if defined(FIRST)
template <class T>
class S1 {
typename T::typeA x;
};
#elif defined(SECOND)
template <class T>
class S1 {
typename T::typeB x;
};
#else
template<class T>
using U1 = S1<T>;
// expected-error@first.h:* {{'DependentType::S1::x' from module 'FirstModule' is not present in definition of 'S1<T>' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif
}
namespace ElaboratedType {
#if defined(FIRST)
namespace N1 { using type = double; }
struct S1 {
N1::type x;
};
#elif defined(SECOND)
namespace N1 { using type = int; }
struct S1 {
N1::type x;
};
#else
S1 s1;
// expected-error@first.h:* {{'ElaboratedType::S1::x' from module 'FirstModule' is not present in definition of 'ElaboratedType::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif
}
namespace Enum {
#if defined(FIRST)
enum A1 {};
struct S1 {
A1 x;
};
#elif defined(SECOND)
enum A2 {};
struct S1 {
A2 x;
};
#else
S1 s1;
// expected-error@first.h:* {{'Enum::S1::x' from module 'FirstModule' is not present in definition of 'Enum::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif
}
namespace NestedNamespaceSpecifier {
#if defined(FIRST)
namespace LevelA1 {
using Type = int;
}
struct S1 {
LevelA1::Type x;
};
# elif defined(SECOND)
namespace LevelB1 {
namespace LevelC1 {
using Type = int;
}
}
struct S1 {
LevelB1::LevelC1::Type x;
};
#else
S1 s1;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'LevelB1::LevelC1::Type' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA1::Type' (aka 'int')}}
#endif
#if defined(FIRST)
namespace LevelA2 { using Type = int; }
struct S2 {
LevelA2::Type x;
};
# elif defined(SECOND)
struct S2 {
int x;
};
#else
S2 s2;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'int'}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA2::Type' (aka 'int')}}
#endif
namespace LevelA3 { using Type = int; }
namespace LevelB3 { using Type = int; }
#if defined(FIRST)
struct S3 {
LevelA3::Type x;
};
# elif defined(SECOND)
struct S3 {
LevelB3::Type x;
};
#else
S3 s3;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'LevelB3::Type' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA3::Type' (aka 'int')}}
#endif
#if defined(FIRST)
struct TA4 { using Type = int; };
struct S4 {
TA4::Type x;
};
# elif defined(SECOND)
struct TB4 { using Type = int; };
struct S4 {
TB4::Type x;
};
#else
S4 s4;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'TB4::Type' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'TA4::Type' (aka 'int')}}
#endif
#if defined(FIRST)
struct T5 { using Type = int; };
struct S5 {
T5::Type x;
};
# elif defined(SECOND)
namespace T5 { using Type = int; };
struct S5 {
T5::Type x;
};
#else
S5 s5;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'T5::Type' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'T5::Type' (aka 'int')}}
#endif
#if defined(FIRST)
namespace N6 {using I = int;}
struct S6 {
NestedNamespaceSpecifier::N6::I x;
};
# elif defined(SECOND)
using I = int;
struct S6 {
::NestedNamespaceSpecifier::I x;
};
#else
S6 s6;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '::NestedNamespaceSpecifier::I' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'NestedNamespaceSpecifier::N6::I' (aka 'int')}}
#endif
#if defined(FIRST)
template <class T, class U>
class S7 {
typename T::type *x = {};
int z = x->T::foo();
};
#elif defined(SECOND)
template <class T, class U>
class S7 {
typename T::type *x = {};
int z = x->U::foo();
};
#else
template <class T, class U>
using U7 = S7<T, U>;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'z' with an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'z' with a different initializer}}
#endif
#if defined(FIRST)
template <class T>
class S8 {
int x = T::template X<int>::value;
};
#elif defined(SECOND)
template <class T>
class S8 {
int x = T::template Y<int>::value;
};
#else
template <class T>
using U8 = S8<T>;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with a different initializer}}
#endif
#if defined(FIRST)
namespace N9 { using I = int; }
namespace O9 = N9;
struct S9 {
O9::I x;
};
#elif defined(SECOND)
namespace N9 { using I = int; }
namespace P9 = N9;
struct S9 {
P9::I x;
};
#else
S9 s9;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'P9::I' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'O9::I' (aka 'int')}}
#endif
}
// Interesting cases that should not cause errors. struct S should not error
// while struct T should error at the access specifier mismatch at the end.

View File

@ -3,6 +3,11 @@
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-local-submodule-visibility -fmodules-cache-path=%t -I%S/Inputs/submodule-visibility -verify %s -DIMPORT
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-local-submodule-visibility -fmodules-cache-path=%t -fmodule-name=x -I%S/Inputs/submodule-visibility -verify %s
// RUN: %clang_cc1 -fimplicit-module-maps -fmodules-local-submodule-visibility -fmodules-cache-path=%t -I%S/Inputs/submodule-visibility -verify %s
//
// Explicit module builds.
// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -emit-module -x c++-module-map %S/Inputs/submodule-visibility/module.modulemap -fmodule-name=other -o %t/other.pcm
// RUN: %clang_cc1 -fmodules -fmodule-map-file=%S/Inputs/submodule-visibility/module.modulemap -fmodules-local-submodule-visibility -fmodule-file=%t/other.pcm -verify -fmodule-name=x -I%S/Inputs/submodule-visibility %s
// RUN: %clang_cc1 -fmodules -fmodule-map-file=%S/Inputs/submodule-visibility/module.modulemap -fmodule-file=%t/other.pcm -verify -fmodule-name=x -I%S/Inputs/submodule-visibility %s -DALLOW_TEXTUAL_NAME_LEAKAGE
#include "a.h"
#include "b.h"
@ -11,6 +16,8 @@
// expected-no-diagnostics
#elif IMPORT
// expected-error@-6 {{could not build module 'x'}}
#elif ALLOW_TEXTUAL_NAME_LEAKAGE
// expected-warning@b.h:7 {{A is defined}}
#else
// The use of -fmodule-name=x causes us to textually include the above headers.
// The submodule visibility rules are still applied in this case.
@ -35,3 +42,5 @@ typedef struct {
int p;
void (*f)(int p);
} name_for_linkage;
void g() { b_template<int>(); }