forked from OSchip/llvm-project
Modules: introduce the __module_private__ declaration specifier, which
indicates that a declaration is only visible within the module it is declared in. llvm-svn: 139348
This commit is contained in:
parent
2bd0401b04
commit
26701a4371
|
@ -180,6 +180,16 @@ public:
|
|||
/// \brief Determine whether this declaration has linkage.
|
||||
bool hasLinkage() const;
|
||||
|
||||
/// \brief Whether this declaration was marked as being private to the
|
||||
/// module in which it was defined.
|
||||
bool isModulePrivate() const { return ModulePrivate; }
|
||||
|
||||
/// \brief Specify whether this declaration was marked as being private
|
||||
/// to the module in which it was defined.
|
||||
void setModulePrivate(bool MP = true) {
|
||||
ModulePrivate = MP;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this declaration is a C++ class member.
|
||||
bool isCXXClassMember() const {
|
||||
const DeclContext *DC = getDeclContext();
|
||||
|
|
|
@ -243,7 +243,7 @@ private:
|
|||
/// evaluated context or not, e.g. functions used in uninstantiated templates
|
||||
/// are regarded as "referenced" but not "used".
|
||||
unsigned Referenced : 1;
|
||||
|
||||
|
||||
protected:
|
||||
/// Access - Used by C++ decls for the access specifier.
|
||||
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
|
||||
|
@ -256,6 +256,10 @@ protected:
|
|||
/// ChangedAfterLoad - if this declaration has changed since being loaded
|
||||
unsigned ChangedAfterLoad : 1;
|
||||
|
||||
/// \brief Whether this declaration is private to the module in which it was
|
||||
/// defined.
|
||||
unsigned ModulePrivate : 1;
|
||||
|
||||
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
|
||||
unsigned IdentifierNamespace : 12;
|
||||
|
||||
|
@ -269,7 +273,9 @@ protected:
|
|||
/// This field is only valid for NamedDecls subclasses.
|
||||
mutable unsigned CachedLinkage : 2;
|
||||
|
||||
|
||||
friend class ASTDeclWriter;
|
||||
friend class ASTDeclReader;
|
||||
|
||||
private:
|
||||
void CheckAccessDeclContext() const;
|
||||
|
||||
|
@ -280,6 +286,7 @@ protected:
|
|||
Loc(L), DeclKind(DK), InvalidDecl(0),
|
||||
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
|
||||
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
|
||||
ModulePrivate(0),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||
HasCachedLinkage(0)
|
||||
{
|
||||
|
@ -290,6 +297,7 @@ protected:
|
|||
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
|
||||
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
|
||||
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
|
||||
ModulePrivate(0),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||
HasCachedLinkage(0)
|
||||
{
|
||||
|
|
|
@ -401,6 +401,7 @@ KEYWORD(__array_extent , KEYCXX)
|
|||
// Apple Extension.
|
||||
KEYWORD(__private_extern__ , KEYALL)
|
||||
KEYWORD(__import_module__ , KEYALL)
|
||||
KEYWORD(__module_private__ , KEYALL)
|
||||
|
||||
// Microsoft Extension.
|
||||
KEYWORD(__declspec , KEYALL)
|
||||
|
|
|
@ -345,7 +345,7 @@ private:
|
|||
SourceRange TypeofParensRange;
|
||||
SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc;
|
||||
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc;
|
||||
SourceLocation FriendLoc, ConstexprLoc;
|
||||
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
|
||||
|
||||
WrittenBuiltinSpecs writtenBS;
|
||||
void SaveWrittenBuiltinSpecs();
|
||||
|
@ -592,13 +592,17 @@ public:
|
|||
|
||||
bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID);
|
||||
|
||||
bool setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID);
|
||||
bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID);
|
||||
|
||||
bool isFriendSpecified() const { return Friend_specified; }
|
||||
SourceLocation getFriendSpecLoc() const { return FriendLoc; }
|
||||
|
||||
bool isModulePrivateSpecified() const { return ModulePrivateLoc.isValid(); }
|
||||
SourceLocation getModulePrivateSpecLoc() const { return ModulePrivateLoc; }
|
||||
|
||||
bool isConstexprSpecified() const { return Constexpr_specified; }
|
||||
SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
|
||||
|
||||
|
|
|
@ -268,7 +268,19 @@ public:
|
|||
|
||||
/// \brief Tests whether the given declaration is acceptable.
|
||||
bool isAcceptableDecl(NamedDecl *D) const {
|
||||
return D->isInIdentifierNamespace(IDNS);
|
||||
if (!D->isInIdentifierNamespace(IDNS))
|
||||
return false;
|
||||
|
||||
// So long as this declaration is not module-private or was parsed as
|
||||
// part of this translation unit (i.e., in the module), we're allowed to
|
||||
// find it.
|
||||
if (!D->isModulePrivate() || D->getPCHLevel() == 0)
|
||||
return true;
|
||||
|
||||
// FIXME: We should be allowed to refer to a module-private name from
|
||||
// within the same module, e.g., during template instantiation.
|
||||
// This requires us know which module a particular declaration came from.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Returns the identifier namespace mask for this lookup.
|
||||
|
|
|
@ -1131,6 +1131,7 @@ public:
|
|||
SourceLocation KWLoc, CXXScopeSpec &SS,
|
||||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
AttributeList *Attr, AccessSpecifier AS,
|
||||
bool IsModulePrivate,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
bool &OwnedDecl, bool &IsDependent, bool ScopedEnum,
|
||||
bool ScopedEnumUsesClassTag, TypeResult UnderlyingType);
|
||||
|
@ -3778,7 +3779,7 @@ public:
|
|||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
AttributeList *Attr,
|
||||
TemplateParameterList *TemplateParams,
|
||||
AccessSpecifier AS,
|
||||
AccessSpecifier AS, bool IsModulePrivate,
|
||||
unsigned NumOuterTemplateParamLists,
|
||||
TemplateParameterList **OuterTemplateParamLists);
|
||||
|
||||
|
|
|
@ -313,8 +313,12 @@ void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
|||
void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
|
||||
std::string S = D->getNameAsString();
|
||||
D->getUnderlyingType().getAsStringInternal(S, Policy);
|
||||
if (!Policy.SuppressSpecifiers)
|
||||
if (!Policy.SuppressSpecifiers) {
|
||||
Out << "typedef ";
|
||||
|
||||
if (D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
}
|
||||
Out << S;
|
||||
}
|
||||
|
||||
|
@ -324,6 +328,8 @@ void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
|
|||
}
|
||||
|
||||
void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
Out << "enum ";
|
||||
if (D->isScoped()) {
|
||||
if (D->isScopedUsingClassTag())
|
||||
|
@ -347,6 +353,8 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
|
|||
}
|
||||
|
||||
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
Out << D->getKindName();
|
||||
if (D->getIdentifier())
|
||||
Out << ' ' << D;
|
||||
|
@ -376,8 +384,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions");
|
||||
}
|
||||
|
||||
if (D->isInlineSpecified()) Out << "inline ";
|
||||
if (D->isInlineSpecified()) Out << "inline ";
|
||||
if (D->isVirtualAsWritten()) Out << "virtual ";
|
||||
if (D->isModulePrivate()) Out << "__module_private__ ";
|
||||
}
|
||||
|
||||
PrintingPolicy SubPolicy(Policy);
|
||||
|
@ -558,6 +567,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
|
||||
if (!Policy.SuppressSpecifiers && D->isMutable())
|
||||
Out << "mutable ";
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
|
||||
std::string Name = D->getNameAsString();
|
||||
D->getType().getAsStringInternal(Name, Policy);
|
||||
|
@ -586,6 +597,8 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
|
|||
|
||||
if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
|
||||
Out << "__thread ";
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
|
||||
std::string Name = D->getNameAsString();
|
||||
QualType T = D->getType();
|
||||
|
@ -650,6 +663,8 @@ void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
|
|||
}
|
||||
|
||||
void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
Out << D->getKindName();
|
||||
if (D->getIdentifier())
|
||||
Out << ' ' << D;
|
||||
|
|
|
@ -1502,6 +1502,7 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
|
|||
/// type-specifier declaration-specifiers[opt]
|
||||
/// [C99] function-specifier declaration-specifiers[opt]
|
||||
/// [GNU] attributes declaration-specifiers[opt]
|
||||
/// [Clang] '__module_private__' declaration-specifiers[opt]
|
||||
///
|
||||
/// storage-class-specifier: [C99 6.7.1]
|
||||
/// 'typedef'
|
||||
|
@ -1952,6 +1953,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
}
|
||||
break;
|
||||
|
||||
// Modules
|
||||
case tok::kw___module_private__:
|
||||
isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID);
|
||||
break;
|
||||
|
||||
// constexpr
|
||||
case tok::kw_constexpr:
|
||||
isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
|
||||
|
@ -2844,7 +2850,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
|
|||
unsigned DiagID;
|
||||
Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
|
||||
StartLoc, SS, Name, NameLoc, attrs.getList(),
|
||||
AS,
|
||||
AS, DS.isModulePrivateSpecified(),
|
||||
MultiTemplateParamsArg(Actions),
|
||||
Owned, IsDependent, IsScopedEnum,
|
||||
IsScopedUsingClassTag, BaseType);
|
||||
|
@ -3207,6 +3213,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
|
|||
case tok::kw_register:
|
||||
case tok::kw___thread:
|
||||
|
||||
// Modules
|
||||
case tok::kw___module_private__:
|
||||
|
||||
// type-specifiers
|
||||
case tok::kw_short:
|
||||
case tok::kw_long:
|
||||
|
|
|
@ -1193,6 +1193,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
// Declaration or definition of a class type
|
||||
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
|
||||
SS, Name, NameLoc, attrs.getList(), AS,
|
||||
DS.isModulePrivateSpecified(),
|
||||
TParams, Owned, IsDependent, false,
|
||||
false, clang::TypeResult());
|
||||
|
||||
|
|
|
@ -553,7 +553,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
|
|||
Tok.is(tok::kw___stdcall) ||
|
||||
Tok.is(tok::kw___fastcall) ||
|
||||
Tok.is(tok::kw___thiscall) ||
|
||||
Tok.is(tok::kw___unaligned))
|
||||
Tok.is(tok::kw___unaligned))
|
||||
return TPResult::True(); // attributes indicate declaration
|
||||
TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
|
||||
if (TPR != TPResult::Ambiguous())
|
||||
|
@ -712,7 +712,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
|
|||
case tok::kw___stdcall:
|
||||
case tok::kw___fastcall:
|
||||
case tok::kw___thiscall:
|
||||
case tok::kw___unaligned:
|
||||
case tok::kw___unaligned:
|
||||
case tok::kw___vector:
|
||||
case tok::kw___pixel:
|
||||
return TPResult::False();
|
||||
|
@ -871,6 +871,9 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
|
|||
case tok::kw_virtual:
|
||||
case tok::kw_explicit:
|
||||
|
||||
// Modules
|
||||
case tok::kw___module_private__:
|
||||
|
||||
// type-specifier:
|
||||
// simple-type-specifier
|
||||
// class-specifier
|
||||
|
@ -906,7 +909,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
|
|||
case tok::kw___ptr64:
|
||||
case tok::kw___ptr32:
|
||||
case tok::kw___forceinline:
|
||||
case tok::kw___unaligned:
|
||||
case tok::kw___unaligned:
|
||||
return TPResult::True();
|
||||
|
||||
// Borland
|
||||
|
|
|
@ -695,6 +695,18 @@ bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID) {
|
||||
if (isModulePrivateSpecified()) {
|
||||
PrevSpec = "__module_private__";
|
||||
DiagID = diag::ext_duplicate_declspec;
|
||||
return true;
|
||||
}
|
||||
|
||||
ModulePrivateLoc = Loc;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
|
||||
unsigned &DiagID) {
|
||||
// 'constexpr constexpr' is ok.
|
||||
|
|
|
@ -3803,6 +3803,9 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
NewVD->setThreadSpecified(true);
|
||||
}
|
||||
|
||||
if (D.getDeclSpec().isModulePrivateSpecified())
|
||||
NewVD->setModulePrivate();
|
||||
|
||||
// Set the lexical context. If the declarator has a C++ scope specifier, the
|
||||
// lexical context will be different from the semantic context.
|
||||
NewVD->setLexicalDeclContext(CurContext);
|
||||
|
@ -4686,6 +4689,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
diag::err_constexpr_dtor);
|
||||
}
|
||||
|
||||
// If __module_private__ was specified, mark the function accordingly.
|
||||
if (D.getDeclSpec().isModulePrivateSpecified()) {
|
||||
NewFD->setModulePrivate();
|
||||
if (FunctionTemplate)
|
||||
FunctionTemplate->setModulePrivate();
|
||||
}
|
||||
|
||||
// Filter out previous declarations that don't match the scope.
|
||||
FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(),
|
||||
|
@ -6970,6 +6979,9 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
|
|||
return NewTD;
|
||||
}
|
||||
|
||||
if (D.getDeclSpec().isModulePrivateSpecified())
|
||||
NewTD->setModulePrivate();
|
||||
|
||||
// C++ [dcl.typedef]p8:
|
||||
// If the typedef declaration defines an unnamed class (or
|
||||
// enum), the first typedef-name declared by the declaration
|
||||
|
@ -7111,6 +7123,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
SourceLocation KWLoc, CXXScopeSpec &SS,
|
||||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
AttributeList *Attr, AccessSpecifier AS,
|
||||
bool IsModulePrivate,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
bool &OwnedDecl, bool &IsDependent,
|
||||
bool ScopedEnum, bool ScopedEnumUsesClassTag,
|
||||
|
@ -7150,6 +7163,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
|
||||
SS, Name, NameLoc, Attr,
|
||||
TemplateParams, AS,
|
||||
IsModulePrivate,
|
||||
TemplateParameterLists.size() - 1,
|
||||
(TemplateParameterList**) TemplateParameterLists.release());
|
||||
return Result.get();
|
||||
|
@ -7712,6 +7726,9 @@ CreateNewDecl:
|
|||
AddMsStructLayoutForRecord(RD);
|
||||
}
|
||||
|
||||
if (IsModulePrivate)
|
||||
New->setModulePrivate();
|
||||
|
||||
// If this is a specialization of a member class (of a class template),
|
||||
// check the specialization.
|
||||
if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
|
||||
|
|
|
@ -9471,6 +9471,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
|
|||
return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc,
|
||||
SS, Name, NameLoc, Attr,
|
||||
TemplateParams, AS_public,
|
||||
/*IsModulePrivate=*/false,
|
||||
TempParamLists.size() - 1,
|
||||
(TemplateParameterList**) TempParamLists.release()).take();
|
||||
} else {
|
||||
|
|
|
@ -811,7 +811,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
AttributeList *Attr,
|
||||
TemplateParameterList *TemplateParams,
|
||||
AccessSpecifier AS,
|
||||
AccessSpecifier AS, bool IsModulePrivate,
|
||||
unsigned NumOuterTemplateParamLists,
|
||||
TemplateParameterList** OuterTemplateParamLists) {
|
||||
assert(TemplateParams && TemplateParams->size() > 0 &&
|
||||
|
@ -1000,6 +1000,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
NewClass, PrevClassTemplate);
|
||||
NewClass->setDescribedClassTemplate(NewTemplate);
|
||||
|
||||
if (IsModulePrivate)
|
||||
NewTemplate->setModulePrivate();
|
||||
|
||||
// Build the type for the class template declaration now.
|
||||
QualType T = NewTemplate->getInjectedClassNameSpecialization();
|
||||
T = Context.getInjectedClassNameType(NewClass, T);
|
||||
|
@ -4931,14 +4934,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
|
|||
// -- The argument list of the specialization shall not be identical
|
||||
// to the implicit argument list of the primary template.
|
||||
Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
|
||||
<< (TUK == TUK_Definition)
|
||||
<< FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
|
||||
<< (TUK == TUK_Definition)
|
||||
<< FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
|
||||
return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
|
||||
ClassTemplate->getIdentifier(),
|
||||
TemplateNameLoc,
|
||||
Attr,
|
||||
TemplateParams,
|
||||
AS_none,
|
||||
AS_none, /*IsModulePrivate=*/false,
|
||||
TemplateParameterLists.size() - 1,
|
||||
(TemplateParameterList**) TemplateParameterLists.release());
|
||||
}
|
||||
|
@ -5973,6 +5976,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
bool IsDependent = false;
|
||||
Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference,
|
||||
KWLoc, SS, Name, NameLoc, Attr, AS_none,
|
||||
/*IsModulePrivate=*/false,
|
||||
MultiTemplateParamsArg(*this, 0, 0),
|
||||
Owned, IsDependent, false, false,
|
||||
TypeResult());
|
||||
|
|
|
@ -248,6 +248,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
|
|||
D->setReferenced(Record[Idx++]);
|
||||
D->setAccess((AccessSpecifier)Record[Idx++]);
|
||||
D->setPCHLevel(Record[Idx++] + (F.Kind <= MK_PCH));
|
||||
D->ModulePrivate = Record[Idx++];
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
|
||||
|
|
|
@ -156,6 +156,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
|
|||
Record.push_back(D->isReferenced());
|
||||
Record.push_back(D->getAccess());
|
||||
Record.push_back(D->getPCHLevel());
|
||||
Record.push_back(D->ModulePrivate);
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
||||
|
@ -185,6 +186,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
|
|||
!D->isInvalidDecl() &&
|
||||
!D->isReferenced() &&
|
||||
D->getAccess() == AS_none &&
|
||||
!D->isModulePrivate() &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier)
|
||||
AbbrevToUse = Writer.getDeclTypedefAbbrev();
|
||||
|
||||
|
@ -234,6 +236,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
|
|||
!D->isInvalidDecl() &&
|
||||
!D->isReferenced() &&
|
||||
D->getAccess() == AS_none &&
|
||||
!D->isModulePrivate() &&
|
||||
!CXXRecordDecl::classofKind(D->getKind()) &&
|
||||
!D->getIntegerTypeSourceInfo() &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier)
|
||||
|
@ -257,6 +260,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
|
|||
!D->isInvalidDecl() &&
|
||||
!D->isReferenced() &&
|
||||
D->getAccess() == AS_none &&
|
||||
!D->isModulePrivate() &&
|
||||
!CXXRecordDecl::classofKind(D->getKind()) &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier)
|
||||
AbbrevToUse = Writer.getDeclRecordAbbrev();
|
||||
|
@ -473,6 +477,7 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
|
|||
!D->isInvalidDecl() &&
|
||||
!D->isReferenced() &&
|
||||
D->getPCHLevel() == 0 &&
|
||||
!D->isModulePrivate() &&
|
||||
!D->getBitWidth() &&
|
||||
!D->hasExtInfo() &&
|
||||
D->getDeclName())
|
||||
|
@ -611,6 +616,7 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
|
|||
!D->isInvalidDecl() &&
|
||||
!D->isReferenced() &&
|
||||
D->getPCHLevel() == 0 &&
|
||||
!D->isModulePrivate() &&
|
||||
!D->getBitWidth() &&
|
||||
!D->hasInClassInitializer() &&
|
||||
!D->hasExtInfo() &&
|
||||
|
@ -663,6 +669,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
|
|||
!D->isInvalidDecl() &&
|
||||
!D->isReferenced() &&
|
||||
D->getAccess() == AS_none &&
|
||||
!D->isModulePrivate() &&
|
||||
D->getPCHLevel() == 0 &&
|
||||
D->getDeclName().getNameKind() == DeclarationName::Identifier &&
|
||||
!D->hasExtInfo() &&
|
||||
|
@ -704,6 +711,7 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
|
|||
!D->isImplicit() &&
|
||||
!D->isUsed(false) &&
|
||||
D->getAccess() == AS_none &&
|
||||
!D->isModulePrivate() &&
|
||||
D->getPCHLevel() == 0 &&
|
||||
D->getStorageClass() == 0 &&
|
||||
!D->hasCXXDirectInitializer() && // Can params have this ever?
|
||||
|
@ -1265,6 +1273,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // PCH level
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
|
||||
|
@ -1296,6 +1305,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // PCH level
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
|
||||
|
@ -1330,6 +1340,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // PCH level
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
|
||||
|
@ -1375,6 +1386,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // PCH level
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
|
||||
|
@ -1414,6 +1426,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // PCH level
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
|
||||
|
@ -1462,6 +1475,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // PCH level
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
|
||||
|
@ -1487,6 +1501,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() {
|
|||
Abv->Add(BitCodeAbbrevOp(0)); // isReferenced
|
||||
Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // PCH level
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate
|
||||
// NamedDecl
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // NameKind = Identifier
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// RUN: mkdir -p %t
|
||||
// RUN: %clang_cc1 -x c++ -emit-module -o %t/left.pcm %s -D MODULE_LEFT
|
||||
// RUN: %clang_cc1 -x c++ -emit-module -o %t/right.pcm %s -D MODULE_RIGHT
|
||||
// RUN: %clang_cc1 -I %t %s -verify
|
||||
|
||||
#if defined(MODULE_LEFT)
|
||||
|
||||
__module_private__ struct HiddenStruct {
|
||||
};
|
||||
|
||||
|
||||
int &f0(int);
|
||||
|
||||
template<typename T>
|
||||
__module_private__ void f1(T*);
|
||||
|
||||
template<typename T>
|
||||
__module_private__ class vector {
|
||||
};
|
||||
|
||||
vector<float> vec_float;
|
||||
|
||||
typedef __module_private__ int Integer;
|
||||
|
||||
#elif defined(MODULE_RIGHT)
|
||||
__module_private__ double &f0(double);
|
||||
|
||||
__module_private__ int hidden_var;
|
||||
|
||||
inline void test_f0_in_right() {
|
||||
double &dr = f0(hidden_var);
|
||||
}
|
||||
#else
|
||||
__import_module__ left;
|
||||
__import_module__ right;
|
||||
|
||||
void test() {
|
||||
int &ir = f0(1.0); // okay: f0() from 'right' is not visible
|
||||
}
|
||||
|
||||
int test_broken() {
|
||||
HiddenStruct hidden; // expected-error{{use of undeclared identifier 'HiddenStruct'}}
|
||||
|
||||
Integer i; // expected-error{{use of undeclared identifier 'Integer'}}
|
||||
|
||||
int *ip = 0;
|
||||
f1(ip); // expected-error{{use of undeclared identifier 'f1'}}
|
||||
|
||||
vector<int> vec; // expected-error{{use of undeclared identifier 'vector'}} \
|
||||
// expected-error{{expected '(' for function-style cast or type construction}} \
|
||||
// expected-error{{use of undeclared identifier 'vec'}}
|
||||
|
||||
return hidden_var; // expected-error{{use of undeclared identifier 'hidden_var'}}
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue