[cfe-commits] r125150 - in /cfe/trunk: include/clang/AST/DeclTemplate.h include/clang/AST/RecursiveASTVisitor.h include/clang/Basic/DeclNodes.td lib/AST/DeclTemplate.cpp lib/Sema/SemaExpr.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp
John McCall
rjmccall at apple.com
Tue Feb 8 17:13:10 PST 2011
Author: rjmccall
Date: Tue Feb 8 19:13:10 2011
New Revision: 125150
URL: http://llvm.org/viewvc/llvm-project?rev=125150&view=rev
Log:
NonTypeTemplateParmDecl is just a DeclaratorDecl, not a VarDecl.
Also, reorganize and make very explicit the logic for determining
the value kind and type of a referenced declaration.
Modified:
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
cfe/trunk/include/clang/Basic/DeclNodes.td
cfe/trunk/lib/AST/DeclTemplate.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Tue Feb 8 19:13:10 2011
@@ -985,7 +985,7 @@
/// template<int Size> class array { };
/// @endcode
class NonTypeTemplateParmDecl
- : public VarDecl, protected TemplateParmPosition {
+ : public DeclaratorDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any, and whether or not
/// it was inherited.
llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited;
@@ -1007,7 +1007,7 @@
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
bool ParameterPack, TypeSourceInfo *TInfo)
- : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
+ : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo),
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
ParameterPack(ParameterPack), ExpandedParameterPack(false),
NumExpandedTypes(0)
@@ -1040,6 +1040,9 @@
using TemplateParmPosition::setPosition;
using TemplateParmPosition::getIndex;
+ SourceLocation getInnerLocStart() const;
+ SourceRange getSourceRange() const;
+
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const {
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Feb 8 19:13:10 2011
@@ -1538,7 +1538,7 @@
DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// A non-type template parameter, e.g. "S" in template<int S> class Foo ...
- TRY_TO(TraverseVarHelper(D));
+ TRY_TO(TraverseDeclaratorHelper(D));
TRY_TO(TraverseStmt(D->getDefaultArgument()));
})
Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
+++ cfe/trunk/include/clang/Basic/DeclNodes.td Tue Feb 8 19:13:10 2011
@@ -42,7 +42,7 @@
def Var : DDecl<Declarator>;
def ImplicitParam : DDecl<Var>;
def ParmVar : DDecl<Var>;
- def NonTypeTemplateParm : DDecl<Var>;
+ def NonTypeTemplateParm : DDecl<Declarator>;
def Template : DDecl<Named, 1>;
def RedeclarableTemplate : DDecl<Template, 1>;
def FunctionTemplate : DDecl<RedeclarableTemplate>;
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Tue Feb 8 19:13:10 2011
@@ -408,7 +408,7 @@
const QualType *ExpandedTypes,
unsigned NumExpandedTypes,
TypeSourceInfo **ExpandedTInfos)
- : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
+ : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo),
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false),
ParameterPack(true), ExpandedParameterPack(true),
NumExpandedTypes(NumExpandedTypes)
@@ -447,6 +447,17 @@
ExpandedTInfos);
}
+SourceLocation NonTypeTemplateParmDecl::getInnerLocStart() const {
+ SourceLocation Start = getTypeSpecStartLoc();
+ if (Start.isInvalid())
+ Start = getLocation();
+ return Start;
+}
+
+SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
+ return SourceRange(getOuterLocStart(), getLocation());
+}
+
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
return hasDefaultArgument()
? getDefaultArgument()->getSourceRange().getBegin()
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb 8 19:13:10 2011
@@ -820,7 +820,7 @@
ValueDecl *value) {
// Only variables ever require capture.
VarDecl *var = dyn_cast<VarDecl>(value);
- if (!var || isa<NonTypeTemplateParmDecl>(var)) return CR_NoCapture;
+ if (!var) return CR_NoCapture;
// Fast path: variables from the current context never require capture.
DeclContext *DC = S.CurContext;
@@ -949,38 +949,25 @@
ExprResult
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
- SourceLocation Loc, const CXXScopeSpec *SS) {
+ SourceLocation Loc,
+ const CXXScopeSpec *SS) {
DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
}
-/// BuildDeclRefExpr - Build a DeclRefExpr.
+/// BuildDeclRefExpr - Build an expression that references a
+/// declaration that does not require a closure capture.
ExprResult
-Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty,
- ExprValueKind VK,
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS) {
- if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) {
+ if (Ty == Context.UndeducedAutoTy) {
Diag(NameInfo.getLoc(),
diag::err_auto_variable_cannot_appear_in_own_initializer)
<< D->getDeclName();
return ExprError();
}
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (isa<NonTypeTemplateParmDecl>(VD)) {
- // Non-type template parameters can be referenced anywhere they are
- // visible.
- Ty = Ty.getNonLValueExprType(Context);
-
- // This ridiculousness brought to you by 'extern void x;' and the
- // GNU compiler collection.
- } else if (!getLangOptions().CPlusPlus && !Ty.hasQualifiers() &&
- Ty->isVoidType()) {
- VK = VK_RValue;
- }
- }
-
MarkDeclarationReferenced(NameInfo.getLoc(), D);
Expr *E = DeclRefExpr::Create(Context,
@@ -1694,24 +1681,6 @@
Diag(Var->getLocation(), diag::note_global_declared_at);
}
}
- } else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) {
- if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) {
- // C99 DR 316 says that, if a function type comes from a
- // function definition (without a prototype), that type is only
- // used for checking compatibility. Therefore, when referencing
- // the function, we pretend that we don't have the full function
- // type.
- if (DiagnoseUseOfDecl(Func, NameLoc))
- return ExprError();
-
- QualType T = Func->getType();
- QualType NoProtoType = T;
- if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>())
- NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType(),
- Proto->getExtInfo());
- // Note that functions are r-values in C.
- return BuildDeclRefExpr(Func, NoProtoType, VK_RValue, NameLoc, &SS);
- }
}
// Check whether this might be a C++ implicit instance member access.
@@ -2325,21 +2294,6 @@
return Owned(ULE);
}
-static ExprValueKind getValueKindForDecl(ASTContext &Context,
- const ValueDecl *D) {
- // FIXME: It's not clear to me why NonTypeTemplateParmDecl is a VarDecl.
- if (isa<VarDecl>(D) && !isa<NonTypeTemplateParmDecl>(D)) return VK_LValue;
- if (isa<FieldDecl>(D)) return VK_LValue;
- if (isa<IndirectFieldDecl>(D)) return VK_LValue;
- if (!Context.getLangOptions().CPlusPlus) return VK_RValue;
- if (isa<FunctionDecl>(D)) {
- if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
- return VK_RValue;
- return VK_LValue;
- }
- return Expr::getValueKindForType(D->getType());
-}
-
/// \brief Complete semantic analysis for a reference to the given declaration.
ExprResult
Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
@@ -2402,15 +2356,6 @@
case CR_Error:
return ExprError();
- case CR_NoCapture: {
- ExprValueKind VK = getValueKindForDecl(Context, VD);
-
- // If this reference is not in a block or if the referenced
- // variable is within the block, create a normal DeclRefExpr.
- return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), VK,
- NameInfo, &SS);
- }
-
case CR_Capture:
assert(!SS.isSet() && "referenced local variable with scope specifier?");
return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ false);
@@ -2418,6 +2363,125 @@
case CR_CaptureByRef:
assert(!SS.isSet() && "referenced local variable with scope specifier?");
return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ true);
+
+ case CR_NoCapture: {
+ // If this reference is not in a block or if the referenced
+ // variable is within the block, create a normal DeclRefExpr.
+
+ QualType type = VD->getType();
+ ExprValueKind valueKind;
+
+ switch (D->getKind()) {
+ // Ignore all the non-ValueDecl kinds.
+#define ABSTRACT_DECL(kind)
+#define VALUE(type, base)
+#define DECL(type, base) \
+ case Decl::type:
+#include "clang/AST/DeclNodes.inc"
+ llvm_unreachable("invalid value decl kind");
+ return ExprError();
+
+ // These shouldn't make it here.
+ case Decl::ObjCAtDefsField:
+ case Decl::ObjCIvar:
+ llvm_unreachable("forming non-member reference to ivar?");
+ return ExprError();
+
+ // Enum constants are always r-values and never references.
+ // Unresolved using declarations are dependent.
+ case Decl::EnumConstant:
+ case Decl::UnresolvedUsingValue:
+ valueKind = VK_RValue;
+ break;
+
+ // Fields and indirect fields that got here must be for
+ // pointer-to-member expressions; we just call them l-values for
+ // internal consistency, because this subexpression doesn't really
+ // exist in the high-level semantics.
+ case Decl::Field:
+ case Decl::IndirectField:
+ assert(getLangOptions().CPlusPlus &&
+ "building reference to field in C?");
+
+ // These can't have reference type in well-formed programs, but
+ // for internal consistency we do this anyway.
+ type = type.getNonReferenceType();
+ valueKind = VK_LValue;
+ break;
+
+ // Non-type template parameters are either l-values or r-values
+ // depending on the type.
+ case Decl::NonTypeTemplateParm: {
+ if (const ReferenceType *reftype = type->getAs<ReferenceType>()) {
+ type = reftype->getPointeeType();
+ valueKind = VK_LValue; // even if the parameter is an r-value reference
+ break;
+ }
+
+ // For non-references, we need to strip qualifiers just in case
+ // the template parameter was declared as 'const int' or whatever.
+ valueKind = VK_RValue;
+ type = type.getUnqualifiedType();
+ break;
+ }
+
+ case Decl::Var:
+ // In C, "extern void blah;" is valid and is an r-value.
+ if (!getLangOptions().CPlusPlus &&
+ !type.hasQualifiers() &&
+ type->isVoidType()) {
+ valueKind = VK_RValue;
+ break;
+ }
+ // fallthrough
+
+ case Decl::ImplicitParam:
+ case Decl::ParmVar:
+ // These are always l-values.
+ valueKind = VK_LValue;
+ type = type.getNonReferenceType();
+ break;
+
+ case Decl::Function: {
+ // Functions are l-values in C++.
+ if (getLangOptions().CPlusPlus) {
+ valueKind = VK_LValue;
+ break;
+ }
+
+ // C99 DR 316 says that, if a function type comes from a
+ // function definition (without a prototype), that type is only
+ // used for checking compatibility. Therefore, when referencing
+ // the function, we pretend that we don't have the full function
+ // type.
+ if (!cast<FunctionDecl>(VD)->hasPrototype())
+ if (const FunctionProtoType *proto = type->getAs<FunctionProtoType>())
+ type = Context.getFunctionNoProtoType(proto->getResultType(),
+ proto->getExtInfo());
+
+ // Functions are r-values in C.
+ valueKind = VK_RValue;
+ break;
+ }
+
+ case Decl::CXXMethod:
+ // C++ methods are l-values if static, r-values if non-static.
+ if (cast<CXXMethodDecl>(VD)->isStatic()) {
+ valueKind = VK_LValue;
+ break;
+ }
+ // fallthrough
+
+ case Decl::CXXConversion:
+ case Decl::CXXDestructor:
+ case Decl::CXXConstructor:
+ valueKind = VK_RValue;
+ break;
+ }
+
+ return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS);
+ }
+
}
llvm_unreachable("unknown capture result");
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Feb 8 19:13:10 2011
@@ -1168,7 +1168,7 @@
}
void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
- VisitVarDecl(D);
+ VisitDeclaratorDecl(D);
// TemplateParmPosition.
D->setDepth(Record[Idx++]);
D->setPosition(Record[Idx++]);
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=125150&r1=125149&r2=125150&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Feb 8 19:13:10 2011
@@ -1009,7 +1009,7 @@
if (D->isExpandedParameterPack())
Record.push_back(D->getNumExpansionTypes());
- VisitVarDecl(D);
+ VisitDeclaratorDecl(D);
// TemplateParmPosition.
Record.push_back(D->getDepth());
Record.push_back(D->getPosition());
More information about the cfe-commits
mailing list