[cfe-commits] r74528 - in /cfe/trunk/lib/Sema: Sema.h SemaExpr.cpp SemaTemplateInstantiateDecl.cpp SemaTemplateInstantiateExpr.cpp
Douglas Gregor
dgregor at apple.com
Tue Jun 30 08:47:49 PDT 2009
Author: dgregor
Date: Tue Jun 30 10:47:41 2009
New Revision: 74528
URL: http://llvm.org/viewvc/llvm-project?rev=74528&view=rev
Log:
Refactor ActOnDeclarationNameExpr into a "parsing action" part and a
"semantic analysis" part. Use the "semantic analysis" part when
performing template instantiation on a DeclRefExpr, rather than an ad
hoc list of rules to construct DeclRefExprs from the instantiation.
A test case for this change will come in with a large commit, which
illustrates what I was actually trying to work on.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=74528&r1=74527&r2=74528&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Jun 30 10:47:41 2009
@@ -1401,7 +1401,11 @@
bool HasTrailingLParen,
const CXXScopeSpec *SS,
bool isAddressOfOperand = false);
-
+ OwningExprResult BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
+ bool HasTrailingLParen,
+ const CXXScopeSpec *SS,
+ bool isAddressOfOperand);
+
virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind);
virtual OwningExprResult ActOnNumericConstant(const Token &);
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=74528&r1=74527&r2=74528&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 30 10:47:41 2009
@@ -970,7 +970,64 @@
return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name);
}
}
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ // Warn about constructs like:
+ // if (void *X = foo()) { ... } else { X }.
+ // In the else block, the pointer is always false.
+
+ // FIXME: In a template instantiation, we don't have scope
+ // information to check this property.
+ if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
+ Scope *CheckS = S;
+ while (CheckS) {
+ if (CheckS->isWithinElse() &&
+ CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
+ if (Var->getType()->isBooleanType())
+ ExprError(Diag(Loc, diag::warn_value_always_false)
+ << Var->getDeclName());
+ else
+ ExprError(Diag(Loc, diag::warn_value_always_zero)
+ << Var->getDeclName());
+ break;
+ }
+
+ // Move up one more control parent to check again.
+ CheckS = CheckS->getControlParent();
+ if (CheckS)
+ CheckS = CheckS->getParent();
+ }
+ }
+ } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) {
+ 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, Loc))
+ return ExprError();
+ QualType T = Func->getType();
+ QualType NoProtoType = T;
+ if (const FunctionProtoType *Proto = T->getAsFunctionProtoType())
+ NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
+ return BuildDeclRefExpr(Func, NoProtoType, Loc, false, false, SS);
+ }
+ }
+
+ return BuildDeclarationNameExpr(Loc, D, HasTrailingLParen, SS, isAddressOfOperand);
+}
+
+/// \brief Complete semantic analysis for a reference to the given declaration.
+Sema::OwningExprResult
+Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,
+ bool HasTrailingLParen,
+ const CXXScopeSpec *SS,
+ bool isAddressOfOperand) {
+ assert(D && "Cannot refer to a NULL declaration");
+ DeclarationName Name = D->getDeclName();
+
// If this is an expression of the form &Class::member, don't build an
// implicit member ref, because we want a pointer to the member in general,
// not any specific instance's member.
@@ -1094,51 +1151,11 @@
// this check when we're going to perform argument-dependent lookup
// on this function name, because this might not be the function
// that overload resolution actually selects.
+ bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) &&
+ HasTrailingLParen;
if (!(ADL && isa<FunctionDecl>(VD)) && DiagnoseUseOfDecl(VD, Loc))
return ExprError();
- if (VarDecl *Var = dyn_cast<VarDecl>(VD)) {
- // Warn about constructs like:
- // if (void *X = foo()) { ... } else { X }.
- // In the else block, the pointer is always false.
-
- // FIXME: In a template instantiation, we don't have scope
- // information to check this property.
- if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
- Scope *CheckS = S;
- while (CheckS) {
- if (CheckS->isWithinElse() &&
- CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
- if (Var->getType()->isBooleanType())
- ExprError(Diag(Loc, diag::warn_value_always_false)
- << Var->getDeclName());
- else
- ExprError(Diag(Loc, diag::warn_value_always_zero)
- << Var->getDeclName());
- break;
- }
-
- // Move up one more control parent to check again.
- CheckS = CheckS->getControlParent();
- if (CheckS)
- CheckS = CheckS->getParent();
- }
- }
- } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(VD)) {
- 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.
- QualType T = Func->getType();
- QualType NoProtoType = T;
- if (const FunctionProtoType *Proto = T->getAsFunctionProtoType())
- NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
- return BuildDeclRefExpr(VD, NoProtoType, Loc, false, false, SS);
- }
- }
-
// Only create DeclRefExpr's for valid Decl's.
if (VD->isInvalidDecl())
return ExprError();
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=74528&r1=74527&r2=74528&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Jun 30 10:47:41 2009
@@ -865,6 +865,6 @@
if (!Function->getBody())
InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function);
- // FIXME: instantiation static member variables
+ // FIXME: instantiate static member variables
}
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=74528&r1=74527&r2=74528&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Tue Jun 30 10:47:41 2009
@@ -156,18 +156,15 @@
false, false));
}
- ValueDecl *NewD
- = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateCurrentDeclRef(D));
- if (!NewD)
+ NamedDecl *InstD = SemaRef.InstantiateCurrentDeclRef(D);
+ if (!InstD)
return SemaRef.ExprError();
- // FIXME: Build QualifiedDeclRefExpr?
- QualType T = NewD->getType();
- return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(NewD,
- T.getNonReferenceType(),
- E->getLocation(),
- T->isDependentType(),
- T->isDependentType()));
+ // FIXME: nested-name-specifier for QualifiedDeclRefExpr
+ return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD,
+ /*FIXME:*/false,
+ /*FIXME:*/0,
+ /*FIXME:*/false);
}
Sema::OwningExprResult
More information about the cfe-commits
mailing list