llvm-capstone/clang/lib/AST/TemplateName.cpp
Douglas Gregor 8b6070bb9d Teach Sema::ActOnCXXNestedNameSpecifier and Sema::CheckTemplateIdType
to cope with non-type templates by providing appropriate
errors. Previously, we would either assert, crash, or silently build a
dependent type when we shouldn't. Fixes PR9226.

llvm-svn: 127037
2011-03-04 21:37:14 +00:00

145 lines
4.8 KiB
C++

//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TemplateName interface and subclasses.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/TemplateName.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace llvm;
TemplateArgument
SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
return TemplateArgument(Arguments, size());
}
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, Parameter, TemplateArgument(Arguments, size()));
}
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context,
TemplateTemplateParmDecl *Parameter,
const TemplateArgument &ArgPack) {
ID.AddPointer(Parameter);
ArgPack.Profile(ID, Context);
}
TemplateName::NameKind TemplateName::getKind() const {
if (Storage.is<TemplateDecl *>())
return Template;
if (Storage.is<DependentTemplateName *>())
return DependentTemplate;
if (Storage.is<QualifiedTemplateName *>())
return QualifiedTemplate;
return getAsOverloadedTemplate()? OverloadedTemplate
: SubstTemplateTemplateParmPack;
}
TemplateDecl *TemplateName::getAsTemplateDecl() const {
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
return Template;
if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
return QTN->getTemplateDecl();
return 0;
}
bool TemplateName::isDependent() const {
if (TemplateDecl *Template = getAsTemplateDecl()) {
if (isa<TemplateTemplateParmDecl>(Template))
return true;
// FIXME: Hack, getDeclContext() can be null if Template is still
// initializing due to PCH reading, so we check it before using it.
// Should probably modify TemplateSpecializationType to allow constructing
// it without the isDependent() checking.
return Template->getDeclContext() &&
Template->getDeclContext()->isDependentContext();
}
assert(!getAsOverloadedTemplate() &&
"overloaded templates shouldn't survive to here");
return true;
}
bool TemplateName::containsUnexpandedParameterPack() const {
if (TemplateDecl *Template = getAsTemplateDecl()) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Template))
return TTP->isParameterPack();
return false;
}
if (DependentTemplateName *DTN = getAsDependentTemplateName())
return DTN->getQualifier() &&
DTN->getQualifier()->containsUnexpandedParameterPack();
return getAsSubstTemplateTemplateParmPack() != 0;
}
void
TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
bool SuppressNNS) const {
if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
OS << Template;
else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
if (!SuppressNNS)
QTN->getQualifier()->print(OS, Policy);
if (QTN->hasTemplateKeyword())
OS << "template ";
OS << QTN->getDecl();
} else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
if (!SuppressNNS && DTN->getQualifier())
DTN->getQualifier()->print(OS, Policy);
OS << "template ";
if (DTN->isIdentifier())
OS << DTN->getIdentifier()->getName();
else
OS << "operator " << getOperatorSpelling(DTN->getOperator());
} else if (SubstTemplateTemplateParmPackStorage *SubstPack
= getAsSubstTemplateTemplateParmPack())
OS << SubstPack->getParameterPack()->getNameAsString();
else {
OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
(*OTS->begin())->printName(OS);
}
}
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
TemplateName N) {
std::string NameStr;
raw_string_ostream OS(NameStr);
LangOptions LO;
LO.CPlusPlus = true;
LO.Bool = true;
N.print(OS, PrintingPolicy(LO));
OS.flush();
return DB << NameStr;
}
void TemplateName::dump() const {
LangOptions LO; // FIXME!
LO.CPlusPlus = true;
LO.Bool = true;
print(llvm::errs(), PrintingPolicy(LO));
}