diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-06-30 15:47:41 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-06-30 15:47:41 +0000 |
commit | 751f9a416a94fe723e6c34fc15fff2ccdf1c4be9 (patch) | |
tree | 7a1f048f5351a034932de0b7ec8a24559a6f3b28 | |
parent | ce2f9bd2bc7dd4e070d46114b6a921127bd1ca86 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74528 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 101 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateExpr.cpp | 17 |
4 files changed, 72 insertions, 54 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 0fa66c4937..42c43291a9 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1401,7 +1401,11 @@ public: 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 &); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 1df3d4f722..1c5b76075e 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -970,7 +970,64 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, 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 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // 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(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 97a160e715..7053bba8ed 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -865,6 +865,6 @@ void Sema::PerformPendingImplicitInstantiations() { if (!Function->getBody()) InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function); - // FIXME: instantiation static member variables + // FIXME: instantiate static member variables } } diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index e1702b52a6..719a9eda47 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -156,18 +156,15 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { 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 |