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/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 67c8777..27d42dd 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -105,9 +105,9 @@
/// provided for a function parameter is well-formed. If so, attach it
/// to the parameter declaration.
void
-Sema::ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc,
+Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
ExprArg defarg) {
- ParmVarDecl *Param = (ParmVarDecl *)param;
+ ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
ExprOwningPtr<Expr> DefaultArg(this, (Expr *)defarg.release());
QualType ParamType = Param->getType();
@@ -153,17 +153,17 @@
/// argument for a function parameter, but we can't parse it yet
/// because we're inside a class definition. Note that this default
/// argument will be parsed later.
-void Sema::ActOnParamUnparsedDefaultArgument(DeclTy *param,
+void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc) {
- ParmVarDecl *Param = (ParmVarDecl*)param;
+ ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
if (Param)
Param->setUnparsedDefaultArg();
}
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
-void Sema::ActOnParamDefaultArgumentError(DeclTy *param) {
- ((ParmVarDecl*)param)->setInvalidDecl();
+void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) {
+ cast<ParmVarDecl>(param.getAs<Decl>())->setInvalidDecl();
}
/// CheckExtraCXXDefaultArguments - Check for any extra default
@@ -179,11 +179,12 @@
// parameter pack. If it is specified in a
// parameter-declaration-clause, it shall not occur within a
// declarator or abstract-declarator of a parameter-declaration.
- for (unsigned i = 0; i < D.getNumTypeObjects(); ++i) {
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = D.getTypeObject(i);
if (chunk.Kind == DeclaratorChunk::Function) {
- for (unsigned argIdx = 0; argIdx < chunk.Fun.NumArgs; ++argIdx) {
- ParmVarDecl *Param = (ParmVarDecl *)chunk.Fun.ArgInfo[argIdx].Param;
+ for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
+ ParmVarDecl *Param =
+ cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param.getAs<Decl>());
if (Param->hasUnparsedDefaultArg()) {
CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
@@ -381,11 +382,11 @@
/// class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
Sema::BaseResult
-Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
+Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
TypeTy *basetype, SourceLocation BaseLoc) {
AdjustDeclIfTemplate(classdecl);
- CXXRecordDecl *Class = cast<CXXRecordDecl>((Decl*)classdecl);
+ CXXRecordDecl *Class = cast<CXXRecordDecl>(classdecl.getAs<Decl>());
QualType BaseType = QualType::getFromOpaquePtr(basetype);
if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
Virtual, Access,
@@ -451,13 +452,13 @@
/// ActOnBaseSpecifiers - Attach the given base specifiers to the
/// class, after checking whether there are any duplicate base
/// classes.
-void Sema::ActOnBaseSpecifiers(DeclTy *ClassDecl, BaseTy **Bases,
+void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
unsigned NumBases) {
if (!ClassDecl || !Bases || !NumBases)
return;
AdjustDeclIfTemplate(ClassDecl);
- AttachBaseSpecifiers(cast<CXXRecordDecl>((Decl*)ClassDecl),
+ AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl.getAs<Decl>()),
(CXXBaseSpecifier**)(Bases), NumBases);
}
@@ -470,10 +471,10 @@
/// bitfield width if there is one and 'InitExpr' specifies the initializer if
/// any. 'LastInGroup' is non-null for cases where one declspec has multiple
/// declarators on it.
-Sema::DeclTy *
+Sema::DeclPtrTy
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
ExprTy *BW, ExprTy *InitExpr,
- DeclTy *LastInGroup) {
+ DeclPtrTy LastInGroup) {
const DeclSpec &DS = D.getDeclSpec();
DeclarationName Name = GetNameForDeclarator(D);
Expr *BitWidth = static_cast<Expr*>(BW);
@@ -552,7 +553,7 @@
AS);
assert(Member && "HandleField never returns null");
} else {
- Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
+ Member = ActOnDeclarator(S, D, LastInGroup).getAs<Decl>();
if (!Member) {
if (BitWidth) DeleteExpr(BitWidth);
return LastInGroup;
@@ -590,18 +591,18 @@
assert((Name || isInstField) && "No identifier for non-field ?");
if (Init)
- AddInitializerToDecl(Member, ExprArg(*this, Init), false);
+ AddInitializerToDecl(DeclPtrTy::make(Member), ExprArg(*this, Init), false);
if (isInstField) {
FieldCollector->Add(cast<FieldDecl>(Member));
return LastInGroup;
}
- return Member;
+ return DeclPtrTy::make(Member);
}
/// ActOnMemInitializer - Handle a C++ member initializer.
Sema::MemInitResult
-Sema::ActOnMemInitializer(DeclTy *ConstructorD,
+Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
Scope *S,
IdentifierInfo *MemberOrBase,
SourceLocation IdLoc,
@@ -610,7 +611,7 @@
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>((Decl*)ConstructorD);
+ = dyn_cast<CXXConstructorDecl>(ConstructorD.getAs<Decl>());
if (!Constructor) {
// The user wrote a constructor initializer on a function that is
// not a C++ constructor. Ignore the error for now, because we may
@@ -706,11 +707,11 @@
return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs);
}
-void Sema::ActOnMemInitializers(DeclTy *ConstructorDecl,
+void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits) {
CXXConstructorDecl *Constructor =
- dyn_cast<CXXConstructorDecl>((Decl *)ConstructorDecl);
+ dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
if (!Constructor) {
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
@@ -917,15 +918,15 @@
}
void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- DeclTy *TagDecl,
+ DeclPtrTy TagDecl,
SourceLocation LBrac,
SourceLocation RBrac) {
TemplateDecl *Template = AdjustDeclIfTemplate(TagDecl);
ActOnFields(S, RLoc, TagDecl,
- (DeclTy**)FieldCollector->getCurFields(),
+ (DeclPtrTy*)FieldCollector->getCurFields(),
FieldCollector->getCurNumFields(), LBrac, RBrac, 0);
- CXXRecordDecl *RD = cast<CXXRecordDecl>((Decl*)TagDecl);
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(TagDecl.getAs<Decl>());
if (!RD->isAbstract()) {
// Collect all the pure virtual methods and see if this is an abstract
// class after all.
@@ -1159,9 +1160,9 @@
/// Method declaration as if we had just parsed the qualified method
/// name. However, it should not bring the parameters into scope;
/// that will be performed by ActOnDelayedCXXMethodParameter.
-void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *MethodD) {
+void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
CXXScopeSpec SS;
- FunctionDecl *Method = (FunctionDecl*)MethodD;
+ FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
QualType ClassTy
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
SS.setScopeRep(
@@ -1174,15 +1175,15 @@
/// function parameter into scope for use in parsing later parts of
/// the method declaration. For example, we could see an
/// ActOnParamDefaultArgument event for this parameter.
-void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *ParamD) {
- ParmVarDecl *Param = (ParmVarDecl*)ParamD;
+void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
+ ParmVarDecl *Param = cast<ParmVarDecl>(ParamD.getAs<Decl>());
// If this parameter has an unparsed default argument, clear it out
// to make way for the parsed default argument.
if (Param->hasUnparsedDefaultArg())
Param->setDefaultArg(0);
- S->AddDecl(Param);
+ S->AddDecl(DeclPtrTy::make(Param));
if (Param->getDeclName())
IdResolver.AddDecl(Param);
}
@@ -1193,8 +1194,8 @@
/// ActOnStartOfFunctionDef action later (not necessarily
/// immediately!) for this method, if it was also defined inside the
/// class body.
-void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *MethodD) {
- FunctionDecl *Method = (FunctionDecl*)MethodD;
+void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
+ FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
CXXScopeSpec SS;
QualType ClassTy
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
@@ -1483,7 +1484,7 @@
/// the declaration of the given C++ conversion function. This routine
/// is responsible for recording the conversion function in the C++
/// class, if possible.
-Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
+Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
assert(Conversion && "Expected to receive a conversion function declaration");
// Set the lexical context of this conversion function
@@ -1528,14 +1529,14 @@
Conv != ConvEnd; ++Conv) {
if (*Conv == Conversion->getPreviousDeclaration()) {
*Conv = Conversion;
- return (DeclTy *)Conversion;
+ return DeclPtrTy::make(Conversion);
}
}
assert(Conversion->isInvalidDecl() && "Conversion should not get here.");
} else
ClassDecl->addConversionFunction(Context, Conversion);
- return (DeclTy *)Conversion;
+ return DeclPtrTy::make(Conversion);
}
//===----------------------------------------------------------------------===//
@@ -1544,10 +1545,10 @@
/// ActOnStartNamespaceDef - This is called at the start of a namespace
/// definition.
-Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
- SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation LBrace) {
+Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
+ SourceLocation IdentLoc,
+ IdentifierInfo *II,
+ SourceLocation LBrace) {
NamespaceDecl *Namespc =
NamespaceDecl::Create(Context, CurContext, IdentLoc, II);
Namespc->setLBracLoc(LBrace);
@@ -1573,9 +1574,9 @@
Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
// Remove the previous declaration from the scope.
- if (DeclRegionScope->isDeclScope(OrigNS)) {
+ if (DeclRegionScope->isDeclScope(DeclPtrTy::make(OrigNS))) {
IdResolver.RemoveDecl(OrigNS);
- DeclRegionScope->RemoveDecl(OrigNS);
+ DeclRegionScope->RemoveDecl(DeclPtrTy::make(OrigNS));
}
} else if (PrevDecl) {
// This is an invalid name redefinition.
@@ -1597,26 +1598,26 @@
// each DeclContext for the namespace has the declarations
// that showed up in that particular namespace definition.
PushDeclContext(NamespcScope, Namespc);
- return Namespc;
+ return DeclPtrTy::make(Namespc);
}
/// ActOnFinishNamespaceDef - This callback is called after a namespace is
/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
-void Sema::ActOnFinishNamespaceDef(DeclTy *D, SourceLocation RBrace) {
- Decl *Dcl = static_cast<Decl *>(D);
+void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) {
+ Decl *Dcl = D.getAs<Decl>();
NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
assert(Namespc && "Invalid parameter, expected NamespaceDecl");
Namespc->setRBracLoc(RBrace);
PopDeclContext();
}
-Sema::DeclTy *Sema::ActOnUsingDirective(Scope *S,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList) {
+Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert(NamespcName && "Invalid NamespcName.");
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
@@ -1629,7 +1630,7 @@
LookupNamespaceName, false);
if (R.isAmbiguous()) {
DiagnoseAmbiguousLookup(R, NamespcName, IdentLoc);
- return 0;
+ return DeclPtrTy();
}
if (NamedDecl *NS = R) {
assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
@@ -1660,7 +1661,7 @@
// FIXME: We ignore attributes for now.
delete AttrList;
- return UDir;
+ return DeclPtrTy::make(UDir);
}
void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
@@ -1672,15 +1673,15 @@
else
// Otherwise it is block-sope. using-directives will affect lookup
// only to the end of scope.
- S->PushUsingDirective(UDir);
+ S->PushUsingDirective(DeclPtrTy::make(UDir));
}
-Sema::DeclTy *Sema::ActOnNamespaceAliasDef(Scope *S,
- SourceLocation AliasLoc,
- IdentifierInfo *Alias,
- const CXXScopeSpec &SS,
- SourceLocation NamespaceLoc,
- IdentifierInfo *NamespaceName) {
+Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ const CXXScopeSpec &SS,
+ SourceLocation NamespaceLoc,
+ IdentifierInfo *NamespaceName) {
// Check if we have a previous declaration with the same name.
if (NamedDecl *PrevDecl = LookupName(S, Alias, LookupOrdinaryName)) {
@@ -1690,7 +1691,7 @@
diag::err_redefinition_different_kind;
Diag(AliasLoc, DiagID) << Alias;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- return 0;
+ return DeclPtrTy();
}
// Lookup the namespace name.
@@ -1698,33 +1699,33 @@
LookupNamespaceName, false);
if (R.isAmbiguous()) {
DiagnoseAmbiguousLookup(R, NamespaceName, NamespaceLoc);
- return 0;
+ return DeclPtrTy();
}
if (!R) {
Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
- return 0;
+ return DeclPtrTy();
}
- return 0;
+ return DeclPtrTy();
}
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
/// e.g: "int x(1);"
-void Sema::AddCXXDirectInitializerToDecl(DeclTy *Dcl, SourceLocation LParenLoc,
+void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
+ SourceLocation LParenLoc,
MultiExprArg Exprs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
unsigned NumExprs = Exprs.size();
assert(NumExprs != 0 && Exprs.get() && "missing expressions");
- Decl *RealDecl = static_cast<Decl *>(Dcl);
+ Decl *RealDecl = Dcl.getAs<Decl>();
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
- if (RealDecl == 0) {
+ if (RealDecl == 0)
return;
- }
VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl);
if (!VDecl) {
@@ -2411,12 +2412,12 @@
/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
/// the '{' brace. Otherwise, this linkage specification does not
/// have any braces.
-Sema::DeclTy *Sema::ActOnStartLinkageSpecification(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation LangLoc,
- const char *Lang,
- unsigned StrSize,
- SourceLocation LBraceLoc) {
+Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation LangLoc,
+ const char *Lang,
+ unsigned StrSize,
+ SourceLocation LBraceLoc) {
LinkageSpecDecl::LanguageIDs Language;
if (strncmp(Lang, "\"C\"", StrSize) == 0)
Language = LinkageSpecDecl::lang_c;
@@ -2424,7 +2425,7 @@
Language = LinkageSpecDecl::lang_cxx;
else {
Diag(LangLoc, diag::err_bad_language);
- return 0;
+ return DeclPtrTy();
}
// FIXME: Add all the various semantics of linkage specifications
@@ -2434,16 +2435,16 @@
LBraceLoc.isValid());
CurContext->addDecl(D);
PushDeclContext(S, D);
- return D;
+ return DeclPtrTy::make(D);
}
/// ActOnFinishLinkageSpecification - Completely the definition of
/// the C++ linkage specification LinkageSpec. If RBraceLoc is
/// valid, it's the position of the closing '}' brace in a linkage
/// specification that uses braces.
-Sema::DeclTy *Sema::ActOnFinishLinkageSpecification(Scope *S,
- DeclTy *LinkageSpec,
- SourceLocation RBraceLoc) {
+Sema::DeclPtrTy Sema::ActOnFinishLinkageSpecification(Scope *S,
+ DeclPtrTy LinkageSpec,
+ SourceLocation RBraceLoc) {
if (LinkageSpec)
PopDeclContext();
return LinkageSpec;
@@ -2451,8 +2452,7 @@
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
/// handler.
-Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
-{
+Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
QualType ExDeclType = GetTypeForDeclarator(D, S);
SourceLocation Begin = D.getDeclSpec().getSourceRange().getBegin();
@@ -2497,11 +2497,10 @@
if (NamedDecl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) {
// The scope should be freshly made just for us. There is just no way
// it contains any previous declaration.
- assert(!S->isDeclScope(PrevDecl));
+ assert(!S->isDeclScope(DeclPtrTy::make(PrevDecl)));
if (PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
-
}
}
@@ -2517,17 +2516,17 @@
}
// Add the exception declaration into this scope.
- S->AddDecl(ExDecl);
+ S->AddDecl(DeclPtrTy::make(ExDecl));
if (II)
IdResolver.AddDecl(ExDecl);
ProcessDeclAttributes(ExDecl, D);
- return ExDecl;
+ return DeclPtrTy::make(ExDecl);
}
-Sema::DeclTy *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
- ExprArg assertexpr,
- ExprArg assertmessageexpr) {
+Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+ ExprArg assertexpr,
+ ExprArg assertmessageexpr) {
Expr *AssertExpr = (Expr *)assertexpr.get();
StringLiteral *AssertMessage =
cast<StringLiteral>((Expr *)assertmessageexpr.get());
@@ -2537,7 +2536,7 @@
if (!AssertExpr->isIntegerConstantExpr(Value, Context)) {
Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) <<
AssertExpr->getSourceRange();
- return 0;
+ return DeclPtrTy();
}
if (Value == 0) {
@@ -2554,11 +2553,11 @@
AssertExpr, AssertMessage);
CurContext->addDecl(Decl);
- return Decl;
+ return DeclPtrTy::make(Decl);
}
-void Sema::SetDeclDeleted(DeclTy *dcl, SourceLocation DelLoc) {
- Decl *Dcl = static_cast<Decl*>(dcl);
+void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {
+ Decl *Dcl = dcl.getAs<Decl>();
FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl);
if (!Fn) {
Diag(DelLoc, diag::err_deleted_non_function);