forked from OSchip/llvm-project
Serialize `#pragma detect_mismatch`.
This is like r262493, but for pragma detect_mismatch instead of pragma comment. The two pragmas have similar behavior, so use the same approach for both. llvm-svn: 262506
This commit is contained in:
parent
65f9d9cd32
commit
cbbaeb1307
|
@ -94,12 +94,6 @@ public:
|
|||
/// The default implementation passes it to HandleTopLevelDecl.
|
||||
virtual void HandleImplicitImportDecl(ImportDecl *D);
|
||||
|
||||
/// \brief Handle a pragma that emits a mismatch identifier and value to the
|
||||
/// object file for the linker to work with. Currently, this only exists to
|
||||
/// support Microsoft's #pragma detect_mismatch.
|
||||
virtual void HandleDetectMismatch(llvm::StringRef Name,
|
||||
llvm::StringRef Value) {}
|
||||
|
||||
/// CompleteTentativeDefinition - Callback invoked at the end of a translation
|
||||
/// unit to notify the consumer that the given tentative definition should be
|
||||
/// completed.
|
||||
|
|
|
@ -138,6 +138,39 @@ public:
|
|||
static bool classofKind(Kind K) { return K == PragmaComment; }
|
||||
};
|
||||
|
||||
/// \brief Represents a `#pragma detect_mismatch` line. Always a child of
|
||||
/// TranslationUnitDecl.
|
||||
class PragmaDetectMismatchDecl final
|
||||
: public Decl,
|
||||
private llvm::TrailingObjects<PragmaDetectMismatchDecl, char> {
|
||||
virtual void anchor();
|
||||
|
||||
size_t ValueStart;
|
||||
|
||||
friend TrailingObjects;
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
|
||||
PragmaDetectMismatchDecl(TranslationUnitDecl *TU, SourceLocation Loc,
|
||||
size_t ValueStart)
|
||||
: Decl(PragmaDetectMismatch, TU, Loc), ValueStart(ValueStart) {}
|
||||
|
||||
public:
|
||||
static PragmaDetectMismatchDecl *Create(const ASTContext &C,
|
||||
TranslationUnitDecl *DC,
|
||||
SourceLocation Loc, StringRef Name,
|
||||
StringRef Value);
|
||||
static PragmaDetectMismatchDecl *
|
||||
CreateDeserialized(ASTContext &C, unsigned ID, unsigned NameValueSize);
|
||||
|
||||
StringRef getName() const { return getTrailingObjects<char>(); }
|
||||
StringRef getValue() const { return getTrailingObjects<char>() + ValueStart; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == PragmaDetectMismatch; }
|
||||
};
|
||||
|
||||
/// \brief Declaration context for names declared as extern "C" in C++. This
|
||||
/// is neither the semantic nor lexical context for such declarations, but is
|
||||
/// used to check for conflicts with other extern "C" declarations. Example:
|
||||
|
|
|
@ -1361,6 +1361,8 @@ DEF_TRAVERSE_DECL(
|
|||
|
||||
DEF_TRAVERSE_DECL(PragmaCommentDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(PragmaDetectMismatchDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(ExternCContextDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
|
||||
|
|
|
@ -12,6 +12,7 @@ class DeclContext { }
|
|||
|
||||
def TranslationUnit : Decl, DeclContext;
|
||||
def PragmaComment : Decl;
|
||||
def PragmaDetectMismatch : Decl;
|
||||
def ExternCContext : Decl, DeclContext;
|
||||
def Named : Decl<1>;
|
||||
def Namespace : DDecl<Named>, DeclContext;
|
||||
|
|
|
@ -44,8 +44,6 @@ public:
|
|||
void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) override;
|
||||
void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override;
|
||||
void HandleImplicitImportDecl(ImportDecl *D) override;
|
||||
void HandleDetectMismatch(llvm::StringRef Name,
|
||||
llvm::StringRef Value) override;
|
||||
void CompleteTentativeDefinition(VarDecl *D) override;
|
||||
void AssignInheritanceModel(CXXRecordDecl *RD) override;
|
||||
void HandleVTable(CXXRecordDecl *RD) override;
|
||||
|
|
|
@ -7676,7 +7676,8 @@ public:
|
|||
void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
|
||||
|
||||
/// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
|
||||
void ActOnPragmaDetectMismatch(StringRef Name, StringRef Value);
|
||||
void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
|
||||
StringRef Value);
|
||||
|
||||
/// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
|
||||
void ActOnPragmaUnused(const Token &Identifier,
|
||||
|
|
|
@ -1166,7 +1166,9 @@ namespace clang {
|
|||
/// \brief An OMPCapturedExprDecl record.
|
||||
DECL_OMP_CAPTUREDEXPR,
|
||||
/// \brief A PragmaCommentDecl record.
|
||||
DECL_PRAGMA_COMMENT
|
||||
DECL_PRAGMA_COMMENT,
|
||||
/// \brief A PragmaDetectMismatchDecl record.
|
||||
DECL_PRAGMA_DETECT_MISMATCH
|
||||
};
|
||||
|
||||
/// \brief Record codes for each kind of statement or expression.
|
||||
|
|
|
@ -8505,6 +8505,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
|||
return false;
|
||||
} else if (isa<PragmaCommentDecl>(D))
|
||||
return true;
|
||||
else if (isa<PragmaDetectMismatchDecl>(D))
|
||||
return true;
|
||||
else if (isa<OMPThreadPrivateDecl>(D))
|
||||
return true;
|
||||
else
|
||||
|
|
|
@ -427,6 +427,7 @@ namespace {
|
|||
void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D);
|
||||
void VisitImportDecl(const ImportDecl *D);
|
||||
void VisitPragmaCommentDecl(const PragmaCommentDecl *D);
|
||||
void VisitPragmaDetectMismatchDecl(const PragmaDetectMismatchDecl *D);
|
||||
|
||||
// C++ Decls
|
||||
void VisitNamespaceDecl(const NamespaceDecl *D);
|
||||
|
@ -1216,6 +1217,12 @@ void ASTDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) {
|
|||
OS << " \"" << Arg << "\"";
|
||||
}
|
||||
|
||||
void ASTDumper::VisitPragmaDetectMismatchDecl(
|
||||
const PragmaDetectMismatchDecl *D) {
|
||||
OS << " \"" << D->getName() << "\" \"" << D->getValue() << "\"";
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// C++ Declarations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -3927,6 +3927,30 @@ PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C,
|
|||
PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown);
|
||||
}
|
||||
|
||||
void PragmaDetectMismatchDecl::anchor() { }
|
||||
|
||||
PragmaDetectMismatchDecl *
|
||||
PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC,
|
||||
SourceLocation Loc, StringRef Name,
|
||||
StringRef Value) {
|
||||
size_t ValueStart = Name.size() + 1;
|
||||
PragmaDetectMismatchDecl *PDMD =
|
||||
new (C, DC, additionalSizeToAlloc<char>(ValueStart + Value.size() + 1))
|
||||
PragmaDetectMismatchDecl(DC, Loc, ValueStart);
|
||||
memcpy(PDMD->getTrailingObjects<char>(), Name.data(), Name.size());
|
||||
PDMD->getTrailingObjects<char>()[Name.size()] = '\0';
|
||||
memcpy(PDMD->getTrailingObjects<char>() + ValueStart, Value.data(),
|
||||
Value.size());
|
||||
PDMD->getTrailingObjects<char>()[ValueStart + Value.size()] = '\0';
|
||||
return PDMD;
|
||||
}
|
||||
|
||||
PragmaDetectMismatchDecl *
|
||||
PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
||||
unsigned NameValueSize) {
|
||||
return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1))
|
||||
PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0);
|
||||
}
|
||||
|
||||
void ExternCContextDecl::anchor() { }
|
||||
|
||||
|
|
|
@ -642,6 +642,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
|||
case StaticAssert:
|
||||
case ObjCPropertyImpl:
|
||||
case PragmaComment:
|
||||
case PragmaDetectMismatch:
|
||||
case Block:
|
||||
case Captured:
|
||||
case TranslationUnit:
|
||||
|
|
|
@ -72,6 +72,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
|||
case Decl::ObjCProperty:
|
||||
case Decl::ObjCCompatibleAlias:
|
||||
case Decl::PragmaComment:
|
||||
case Decl::PragmaDetectMismatch:
|
||||
case Decl::AccessSpec:
|
||||
case Decl::LinkageSpec:
|
||||
case Decl::ObjCPropertyImpl:
|
||||
|
|
|
@ -205,11 +205,6 @@ namespace clang {
|
|||
Gen->HandleVTable(RD);
|
||||
}
|
||||
|
||||
void HandleDetectMismatch(llvm::StringRef Name,
|
||||
llvm::StringRef Value) override {
|
||||
Gen->HandleDetectMismatch(Name, Value);
|
||||
}
|
||||
|
||||
static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
|
||||
unsigned LocCookie) {
|
||||
SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
|
||||
|
|
|
@ -3748,6 +3748,12 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
|||
break;
|
||||
}
|
||||
|
||||
case Decl::PragmaDetectMismatch: {
|
||||
const auto *PDMD = cast<PragmaDetectMismatchDecl>(D);
|
||||
AddDetectMismatch(PDMD->getName(), PDMD->getValue());
|
||||
break;
|
||||
}
|
||||
|
||||
case Decl::LinkageSpec:
|
||||
EmitLinkageSpec(cast<LinkageSpecDecl>(D));
|
||||
break;
|
||||
|
|
|
@ -233,11 +233,6 @@ namespace {
|
|||
|
||||
Builder->EmitVTable(RD);
|
||||
}
|
||||
|
||||
void HandleDetectMismatch(llvm::StringRef Name,
|
||||
llvm::StringRef Value) override {
|
||||
Builder->AddDetectMismatch(Name, Value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -317,11 +317,6 @@ void MultiplexConsumer::HandleImplicitImportDecl(ImportDecl *D) {
|
|||
Consumer->HandleImplicitImportDecl(D);
|
||||
}
|
||||
|
||||
void MultiplexConsumer::HandleDetectMismatch(llvm::StringRef Name, llvm::StringRef Value) {
|
||||
for (auto &Consumer : Consumers)
|
||||
Consumer->HandleDetectMismatch(Name, Value);
|
||||
}
|
||||
|
||||
void MultiplexConsumer::CompleteTentativeDefinition(VarDecl *D) {
|
||||
for (auto &Consumer : Consumers)
|
||||
Consumer->CompleteTentativeDefinition(D);
|
||||
|
|
|
@ -1722,10 +1722,10 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP,
|
|||
void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
|
||||
PragmaIntroducerKind Introducer,
|
||||
Token &Tok) {
|
||||
SourceLocation CommentLoc = Tok.getLocation();
|
||||
SourceLocation DetectMismatchLoc = Tok.getLocation();
|
||||
PP.Lex(Tok);
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
|
||||
PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1760,10 +1760,10 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
|
|||
|
||||
// If the pragma is lexically sound, notify any interested PPCallbacks.
|
||||
if (PP.getPPCallbacks())
|
||||
PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
|
||||
PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
|
||||
ValueString);
|
||||
|
||||
Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
|
||||
Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
|
||||
}
|
||||
|
||||
/// \brief Handle the microsoft \#pragma comment extension.
|
||||
|
|
|
@ -277,9 +277,12 @@ void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc,
|
|||
Consumer.HandleTopLevelDecl(DeclGroupRef(PCD));
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) {
|
||||
// FIXME: Serialize this.
|
||||
Consumer.HandleDetectMismatch(Name, Value);
|
||||
void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
|
||||
StringRef Value) {
|
||||
auto *PDMD = PragmaDetectMismatchDecl::Create(
|
||||
Context, Context.getTranslationUnitDecl(), Loc, Name, Value);
|
||||
Context.getTranslationUnitDecl()->addDecl(PDMD);
|
||||
Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD));
|
||||
}
|
||||
|
||||
void Sema::ActOnPragmaMSPointersToMembers(
|
||||
|
|
|
@ -338,6 +338,11 @@ TemplateDeclInstantiator::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
|
|||
llvm_unreachable("pragma comment cannot be instantiated");
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitPragmaDetectMismatchDecl(
|
||||
PragmaDetectMismatchDecl *D) {
|
||||
llvm_unreachable("pragma comment cannot be instantiated");
|
||||
}
|
||||
|
||||
Decl *
|
||||
TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) {
|
||||
llvm_unreachable("extern \"C\" context cannot be instantiated");
|
||||
|
|
|
@ -320,6 +320,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
|
|||
case Decl::LinkageSpec:
|
||||
case Decl::ObjCPropertyImpl:
|
||||
case Decl::PragmaComment:
|
||||
case Decl::PragmaDetectMismatch:
|
||||
case Decl::FileScopeAsm:
|
||||
case Decl::AccessSpec:
|
||||
case Decl::Friend:
|
||||
|
|
|
@ -243,6 +243,7 @@ namespace clang {
|
|||
|
||||
void VisitDecl(Decl *D);
|
||||
void VisitPragmaCommentDecl(PragmaCommentDecl *D);
|
||||
void VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D);
|
||||
void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
|
||||
void VisitNamedDecl(NamedDecl *ND);
|
||||
void VisitLabelDecl(LabelDecl *LD);
|
||||
|
@ -552,6 +553,20 @@ void ASTDeclReader::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
|
|||
D->getTrailingObjects<char>()[Arg.size()] = '\0';
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D) {
|
||||
VisitDecl(D);
|
||||
D->setLocation(ReadSourceLocation(Record, Idx));
|
||||
std::string Name = ReadString(Record, Idx);
|
||||
memcpy(D->getTrailingObjects<char>(), Name.data(), Name.size());
|
||||
D->getTrailingObjects<char>()[Name.size()] = '\0';
|
||||
|
||||
D->ValueStart = Name.size() + 1;
|
||||
std::string Value = ReadString(Record, Idx);
|
||||
memcpy(D->getTrailingObjects<char>() + D->ValueStart, Value.data(),
|
||||
Value.size());
|
||||
D->getTrailingObjects<char>()[D->ValueStart + Value.size()] = '\0';
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
|
||||
llvm_unreachable("Translation units are not serialized");
|
||||
}
|
||||
|
@ -2433,6 +2448,7 @@ static bool isConsumerInterestedIn(Decl *D, bool HasBody) {
|
|||
isa<ObjCImplDecl>(D) ||
|
||||
isa<ImportDecl>(D) ||
|
||||
isa<PragmaCommentDecl>(D) ||
|
||||
isa<PragmaDetectMismatchDecl>(D) ||
|
||||
isa<OMPThreadPrivateDecl>(D))
|
||||
return true;
|
||||
if (VarDecl *Var = dyn_cast<VarDecl>(D))
|
||||
|
@ -3353,6 +3369,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
|
|||
case DECL_PRAGMA_COMMENT:
|
||||
D = PragmaCommentDecl::CreateDeserialized(Context, ID, Record[Idx++]);
|
||||
break;
|
||||
case DECL_PRAGMA_DETECT_MISMATCH:
|
||||
D = PragmaDetectMismatchDecl::CreateDeserialized(Context, ID,
|
||||
Record[Idx++]);
|
||||
break;
|
||||
case DECL_EMPTY:
|
||||
D = EmptyDecl::CreateDeserialized(Context, ID);
|
||||
break;
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace clang {
|
|||
|
||||
void VisitDecl(Decl *D);
|
||||
void VisitPragmaCommentDecl(PragmaCommentDecl *D);
|
||||
void VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D);
|
||||
void VisitTranslationUnitDecl(TranslationUnitDecl *D);
|
||||
void VisitNamedDecl(NamedDecl *D);
|
||||
void VisitLabelDecl(LabelDecl *LD);
|
||||
|
@ -326,6 +327,18 @@ void ASTDeclWriter::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
|
|||
Code = serialization::DECL_PRAGMA_COMMENT;
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitPragmaDetectMismatchDecl(
|
||||
PragmaDetectMismatchDecl *D) {
|
||||
StringRef Name = D->getName();
|
||||
StringRef Value = D->getValue();
|
||||
Record.push_back(Name.size() + 1 + Value.size());
|
||||
VisitDecl(D);
|
||||
Writer.AddSourceLocation(D->getLocStart(), Record);
|
||||
Writer.AddString(Name, Record);
|
||||
Writer.AddString(Value, Record);
|
||||
Code = serialization::DECL_PRAGMA_DETECT_MISMATCH;
|
||||
}
|
||||
|
||||
void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
||||
llvm_unreachable("Translation units aren't directly serialized");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Test this without pch.
|
||||
// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple x86_64-pc-win32 -fms-extensions -emit-llvm -include %s -o - | FileCheck %s
|
||||
|
||||
// Test with pch.
|
||||
// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple x86_64-pc-win32 -fms-extensions -emit-pch -o %t
|
||||
// RUN: %clang_cc1 %s -Wunknown-pragmas -Werror -triple x86_64-pc-win32 -fms-extensions -emit-llvm -include-pch %t -o - | FileCheck %s
|
||||
|
||||
// The first run line creates a pch, and since at that point HEADER is not
|
||||
// defined, the only thing contained in the pch is the pragma. The second line
|
||||
// then includes that pch, so HEADER is defined and the actual code is compiled.
|
||||
// The check then makes sure that the pragma is in effect in the file that
|
||||
// includes the pch.
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
#pragma detect_mismatch("FruitKind", "Jaboticaba")
|
||||
|
||||
#else
|
||||
|
||||
// CHECK: "/DEFAULTLIB:foo.lib"
|
||||
// CHECK: "/FAILIFMISMATCH:\22FruitKind=Jaboticaba\22"
|
||||
|
||||
#endif
|
|
@ -5587,6 +5587,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
|||
case Decl::ObjCTypeParam:
|
||||
case Decl::BuiltinTemplate:
|
||||
case Decl::PragmaComment:
|
||||
case Decl::PragmaDetectMismatch:
|
||||
return C;
|
||||
|
||||
// Declaration kinds that don't make any sense here, but are
|
||||
|
|
Loading…
Reference in New Issue