Introduce a new OpaquePtr<N> struct type, which is a simple POD wrapper for a
pointer. Its purpose in life is to be a glorified void*, but which does not
implicitly convert to void* or other OpaquePtr's with a different UID.
Introduce Action::DeclPtrTy which is a typedef for OpaquePtr<0>. Change the
entire parser/sema interface to use DeclPtrTy instead of DeclTy*. This
makes the C++ compiler enforce that these aren't convertible to other opaque
types.
We should also convert ExprTy, StmtTy, TypeTy, AttrTy, BaseTy, etc,
but I don't plan to do that in the short term.
The one outstanding known problem with this patch is that we lose the
bitmangling optimization where ActionResult<DeclPtrTy> doesn't know how to
bitmangle the success bit into the low bit of DeclPtrTy. I will rectify
this with a subsequent patch.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67952 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 7f2c5d3..00a3349 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -27,7 +27,7 @@
CurScope = 0;
NumCachedScopes = 0;
ParenCount = BracketCount = BraceCount = 0;
- ObjCImpDecl = 0;
+ ObjCImpDecl = DeclPtrTy();
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
@@ -324,8 +324,8 @@
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
/// action tells us to. This returns true if the EOF was encountered.
-bool Parser::ParseTopLevelDecl(DeclTy*& Result) {
- Result = 0;
+bool Parser::ParseTopLevelDecl(DeclPtrTy &Result) {
+ Result = DeclPtrTy();
if (Tok.is(tok::eof)) {
Actions.ActOnEndOfTranslationUnit();
return true;
@@ -342,7 +342,7 @@
void Parser::ParseTranslationUnit() {
Initialize();
- DeclTy *Res;
+ DeclPtrTy Res;
while (!ParseTopLevelDecl(Res))
/*parse them all*/;
@@ -368,20 +368,20 @@
/// [GNU] asm-definition:
/// simple-asm-expr ';'
///
-Parser::DeclTy *Parser::ParseExternalDeclaration() {
+Parser::DeclPtrTy Parser::ParseExternalDeclaration() {
switch (Tok.getKind()) {
case tok::semi:
Diag(Tok, diag::ext_top_level_semi);
ConsumeToken();
// TODO: Invoke action for top-level semicolon.
- return 0;
+ return DeclPtrTy();
case tok::r_brace:
Diag(Tok, diag::err_expected_external_declaration);
ConsumeBrace();
- return 0;
+ return DeclPtrTy();
case tok::eof:
Diag(Tok, diag::err_expected_external_declaration);
- return 0;
+ return DeclPtrTy();
case tok::kw___extension__: {
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
@@ -396,7 +396,7 @@
if (!Result.isInvalid())
return Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result));
- return 0;
+ return DeclPtrTy();
}
case tok::at:
// @ is not a legal token unless objc is enabled, no need to check.
@@ -405,11 +405,9 @@
case tok::plus:
if (getLang().ObjC1)
return ParseObjCMethodDefinition();
- else {
- Diag(Tok, diag::err_expected_external_declaration);
- ConsumeToken();
- }
- return 0;
+ Diag(Tok, diag::err_expected_external_declaration);
+ ConsumeToken();
+ return DeclPtrTy();
case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
@@ -440,7 +438,7 @@
/// [!C99] init-declarator-list ';' [TODO: warn in c99 mode]
/// [OMP] threadprivate-directive [TODO]
///
-Parser::DeclTy *
+Parser::DeclPtrTy
Parser::ParseDeclarationOrFunctionDefinition(
TemplateParameterLists *TemplateParams,
AccessSpecifier AS) {
@@ -464,7 +462,7 @@
!Tok.isObjCAtKeyword(tok::objc_protocol)) {
Diag(Tok, diag::err_objc_unexpected_attr);
SkipUntil(tok::semi); // FIXME: better skip?
- return 0;
+ return DeclPtrTy();
}
const char *PrevSpec = 0;
if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec))
@@ -491,7 +489,7 @@
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
ConsumeToken();
- return 0;
+ return DeclPtrTy();
}
// If the declarator is the start of a function definition, handle it.
@@ -521,7 +519,7 @@
} else {
SkipUntil(tok::semi);
}
- return 0;
+ return DeclPtrTy();
}
return ParseFunctionDefinition(DeclaratorInfo);
} else {
@@ -530,7 +528,7 @@
else
Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
SkipUntil(tok::semi);
- return 0;
+ return DeclPtrTy();
}
// Parse the init-declarator-list for a normal declaration.
@@ -550,7 +548,7 @@
/// [C++] function-definition: [C++ 8.4]
/// decl-specifier-seq[opt] declarator function-try-block [TODO]
///
-Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) {
+Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) {
const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
"This isn't a function declarator!");
@@ -584,7 +582,7 @@
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
- return 0;
+ return DeclPtrTy();
}
// Enter a scope for the function body.
@@ -592,7 +590,7 @@
// Tell the actions module that we have entered a function definition with the
// specified Declarator for the function.
- DeclTy *Res = Actions.ActOnStartOfFunctionDef(CurScope, D);
+ DeclPtrTy Res = Actions.ActOnStartOfFunctionDef(CurScope, D);
// If we have a colon, then we're probably parsing a C++
// ctor-initializer.
@@ -652,14 +650,14 @@
// Handle the full declarator list.
while (1) {
- DeclTy *AttrList;
+ Action::AttrTy *AttrList;
// If attributes are present, parse them.
if (Tok.is(tok::kw___attribute))
// FIXME: attach attributes too.
AttrList = ParseAttributes();
// Ask the actions module to compute the type for this declarator.
- Action::DeclTy *Param =
+ Action::DeclPtrTy Param =
Actions.ActOnParamDeclarator(CurScope, ParmDeclarator);
if (Param &&
@@ -862,7 +860,7 @@
// If this is a template-id, annotate with a template-id or type token.
if (NextToken().is(tok::less)) {
- DeclTy *Template;
+ DeclPtrTy Template;
if (TemplateNameKind TNK
= Actions.isTemplateName(*Tok.getIdentifierInfo(),
CurScope, Template, &SS))