Don't rely on a StringRef being null-terminated (it's not) for deprecation messages.

Store pointer and length of the message in DelayedDiagnostic and hide the gory union details.

llvm-svn: 116153
This commit is contained in:
Benjamin Kramer
2010-10-09 15:49:00 +00:00
parent 9cc3fcc8ec
commit bfac7dcda0
4 changed files with 40 additions and 24 deletions

View File

@@ -119,14 +119,6 @@ public:
SourceLocation Loc;
union {
/// Deprecation.
struct { NamedDecl *Decl; const char* Message; } DeprecationData;
/// Access control.
char AccessData[sizeof(AccessedEntity)];
};
void destroy() {
switch (Kind) {
case Access: getAccessData().~AccessedEntity(); break;
@@ -135,14 +127,15 @@ public:
}
static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
NamedDecl *D,
const char *Msg) {
const NamedDecl *D,
llvm::StringRef Msg) {
DelayedDiagnostic DD;
DD.Kind = Deprecation;
DD.Triggered = false;
DD.Loc = Loc;
DD.DeprecationData.Decl = D;
DD.DeprecationData.Message = Msg;
DD.DeprecationData.Message = Msg.data();
DD.DeprecationData.MessageLen = Msg.size();
return DD;
}
@@ -157,11 +150,37 @@ public:
}
AccessedEntity &getAccessData() {
assert(Kind == Access && "Not an access diagnostic.");
return *reinterpret_cast<AccessedEntity*>(AccessData);
}
const AccessedEntity &getAccessData() const {
assert(Kind == Access && "Not an access diagnostic.");
return *reinterpret_cast<const AccessedEntity*>(AccessData);
}
const NamedDecl *getDeprecationDecl() const {
assert(Kind == Deprecation && "Not a deprecation diagnostic.");
return DeprecationData.Decl;
}
llvm::StringRef getDeprecationMessage() const {
assert(Kind == Deprecation && "Not a deprecation diagnostic.");
return llvm::StringRef(DeprecationData.Message,
DeprecationData.MessageLen);
}
private:
union {
/// Deprecation.
struct {
const NamedDecl *Decl;
const char *Message;
size_t MessageLen;
} DeprecationData;
/// Access control.
char AccessData[sizeof(AccessedEntity)];
};
};
}

View File

@@ -1650,7 +1650,7 @@ public:
ParsingDeclStackState PushParsingDeclaration();
void PopParsingDeclaration(ParsingDeclStackState S, Decl *D);
void EmitDeprecationWarning(NamedDecl *D, const char *Message,
void EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
SourceLocation Loc);
void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);

View File

@@ -2566,16 +2566,16 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
return;
DD.Triggered = true;
if (DD.DeprecationData.Message)
if (!DD.getDeprecationMessage().empty())
Diag(DD.Loc, diag::warn_deprecated_message)
<< DD.DeprecationData.Decl->getDeclName()
<< DD.DeprecationData.Message;
<< DD.getDeprecationDecl()->getDeclName()
<< DD.getDeprecationMessage();
else
Diag(DD.Loc, diag::warn_deprecated)
<< DD.DeprecationData.Decl->getDeclName();
<< DD.getDeprecationDecl()->getDeclName();
}
void Sema::EmitDeprecationWarning(NamedDecl *D, const char * Message,
void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
SourceLocation Loc) {
// Delay if we're currently parsing a declaration.
if (ParsingDeclDepth) {
@@ -2587,7 +2587,7 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, const char * Message,
// Otherwise, don't warn if our current context is deprecated.
if (isDeclDeprecated(cast<Decl>(CurContext)))
return;
if (Message)
if (!Message.empty())
Diag(Loc, diag::warn_deprecated_message) << D->getDeclName()
<< Message;
else

View File

@@ -57,11 +57,8 @@ using namespace sema;
///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
// See if the decl is deprecated.
if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>()) {
const char *Message =
DA->getMessage().empty() ? 0 : DA->getMessage().data();
EmitDeprecationWarning(D, Message, Loc);
}
if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
EmitDeprecationWarning(D, DA->getMessage(), Loc);
// See if the decl is unavailable
if (const UnavailableAttr *UA = D->getAttr<UnavailableAttr>()) {
@@ -69,7 +66,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
Diag(Loc, diag::err_unavailable) << D->getDeclName();
else
Diag(Loc, diag::err_unavailable_message)
<< D->getDeclName() << UA->getMessage().data();
<< D->getDeclName() << UA->getMessage();
Diag(D->getLocation(), diag::note_unavailable_here) << 0;
}