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:
Nico Weber 2016-03-02 19:28:54 +00:00
parent 65f9d9cd32
commit cbbaeb1307
24 changed files with 155 additions and 32 deletions

View File

@ -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.

View File

@ -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:

View File

@ -1361,6 +1361,8 @@ DEF_TRAVERSE_DECL(
DEF_TRAVERSE_DECL(PragmaCommentDecl, {})
DEF_TRAVERSE_DECL(PragmaDetectMismatchDecl, {})
DEF_TRAVERSE_DECL(ExternCContextDecl, {})
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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() { }

View File

@ -642,6 +642,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case StaticAssert:
case ObjCPropertyImpl:
case PragmaComment:
case PragmaDetectMismatch:
case Block:
case Captured:
case TranslationUnit:

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -233,11 +233,6 @@ namespace {
Builder->EmitVTable(RD);
}
void HandleDetectMismatch(llvm::StringRef Name,
llvm::StringRef Value) override {
Builder->AddDetectMismatch(Name, Value);
}
};
}

View File

@ -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);

View File

@ -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.

View File

@ -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(

View File

@ -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");

View File

@ -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:

View File

@ -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;

View File

@ -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");
}

View File

@ -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

View File

@ -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