data: fixed crashed when parsing own code

* fixed test that was expecting a wrong result.
* refactored DataType class.
* added code to parse dependent type names.
* refactored utilityCxx a little.
This commit is contained in:
malte_langkabel
2015-03-23 17:00:54 +01:00
parent c83dbae4d4
commit 3738f196b9
38 changed files with 781 additions and 659 deletions
+1 -1
View File
@@ -2,8 +2,8 @@
/bin/app/Debug/
/bin/app/data/log/
/bin/app/data/projects/
/bin/app/data/ApplicationSettings.xml
/bin/app/data/ProjectSettings.xml
/bin/app/data/window_settings.ini
/bin/app/Release/
+14 -14
View File
@@ -1,4 +1,4 @@
ConfigManager.cpp ERROR: value path/to/nowhere is not present in config.
ConfigManager.cpp WARNING: value path/to/nowhere is not present in config.
Storage.cpp INFO: file: input.cc < 0:0 0:0>
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
@@ -57,20 +57,20 @@ Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
Edge.cpp ERROR: Edge usage can't go from Node undefined to Node undefined
Settings.cpp WARNING: File for Settings not found.
ConfigManager.cpp ERROR: value Bool is not present in config.
ConfigManager.cpp ERROR: value Int is not present in config.
ConfigManager.cpp ERROR: value Float is not present in config.
ConfigManager.cpp ERROR: value String is not present in config.
ConfigManager.cpp WARNING: value Bool is not present in config.
ConfigManager.cpp WARNING: value Int is not present in config.
ConfigManager.cpp WARNING: value Float is not present in config.
ConfigManager.cpp WARNING: value String is not present in config.
Settings.cpp WARNING: File for Settings not found.
ConfigManager.cpp ERROR: value Bool is not present in config.
ConfigManager.cpp ERROR: value Int is not present in config.
ConfigManager.cpp ERROR: value Float is not present in config.
ConfigManager.cpp ERROR: value String is not present in config.
ConfigManager.cpp ERROR: value Bool is not present in config.
ConfigManager.cpp ERROR: value Int is not present in config.
ConfigManager.cpp ERROR: value Float is not present in config.
ConfigManager.cpp ERROR: value String is not present in config.
ConfigManager.cpp ERROR: value NewBool is not present in config.
ConfigManager.cpp WARNING: value Bool is not present in config.
ConfigManager.cpp WARNING: value Int is not present in config.
ConfigManager.cpp WARNING: value Float is not present in config.
ConfigManager.cpp WARNING: value String is not present in config.
ConfigManager.cpp WARNING: value Bool is not present in config.
ConfigManager.cpp WARNING: value Int is not present in config.
ConfigManager.cpp WARNING: value Float is not present in config.
ConfigManager.cpp WARNING: value String is not present in config.
ConfigManager.cpp WARNING: value NewBool is not present in config.
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
Storage.cpp INFO: typedef: type -> int <file.cpp 1:1 1:1>
Storage.cpp INFO: class: Class <file.cpp 1:1 1:1>
+10 -13
View File
@@ -170,21 +170,18 @@ add_files(
data/search/SearchResult.cpp
data/search/SearchResult.h
data/type/modifier/DataTypeModifier.cpp
data/type/modifier/DataTypeModifier.h
data/type/modifier/DataTypeModifierArray.cpp
data/type/modifier/DataTypeModifierArray.h
data/type/modifier/DataTypeModifierPointer.cpp
data/type/modifier/DataTypeModifierPointer.h
data/type/modifier/DataTypeModifierReference.cpp
data/type/modifier/DataTypeModifierReference.h
data/type/ArrayModifiedDataType.cpp
data/type/ArrayModifiedDataType.h
data/type/DataType.cpp
data/type/DataType.h
data/type/DataTypeModifierStack.cpp
data/type/DataTypeModifierStack.h
data/type/DataTypeQualifierList.cpp
data/type/DataTypeQualifierList.h
data/type/ModifiedDataType.cpp
data/type/ModifiedDataType.h
data/type/NamedDataType.cpp
data/type/NamedDataType.h
data/type/PointerModifiedDataType.cpp
data/type/PointerModifiedDataType.h
data/type/ReferenceModifiedDataType.cpp
data/type/ReferenceModifiedDataType.h
data/Storage.cpp
data/Storage.h
+6 -6
View File
@@ -200,7 +200,7 @@ Id Storage::onTypedefParsed(
const ParseLocation& location, const std::vector<std::string>& nameHierarchy, const ParseTypeUsage& underlyingType,
AccessType access
){
log("typedef", utility::join(nameHierarchy, "::") + " -> " + underlyingType.dataType.getFullTypeName(), location);
log("typedef", utility::join(nameHierarchy, "::") + " -> " + underlyingType.dataType->getFullTypeName(), location);
Node* node = addNodeHierarchy(Node::NODE_TYPEDEF, nameHierarchy);
addAccess(node, access);
@@ -503,7 +503,7 @@ Id Storage::onEnumConstantUsageParsed(
Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function)
{
log("type usage", function.getFullName() + " -> " + type.dataType.getRawTypeName(), type.location);
log("type usage", function.getFullName() + " -> " + type.dataType->getRawTypeName(), type.location);
Node* functionNode = addNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED_FUNCTION, function);
Edge* edge = addTypeEdge(functionNode, Edge::EDGE_TYPE_USAGE, type);
@@ -519,7 +519,7 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& f
Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseVariable& variable)
{
log("type usage", variable.getFullName() + " -> " + type.dataType.getRawTypeName(), type.location);
log("type usage", variable.getFullName() + " -> " + type.dataType->getRawTypeName(), type.location);
Node* variableNode = addNodeHierarchy(Node::NODE_UNDEFINED, variable.nameHierarchy);
Edge* edge = addTypeEdge(variableNode, Edge::EDGE_TYPE_USAGE, type);
@@ -560,13 +560,13 @@ Id Storage::onTemplateDefaultArgumentTypeParsed(
){
log(
"template default argument",
utility::join(defaultArgumentType.dataType.getTypeNameHierarchy(), "::") +
utility::join(defaultArgumentType.dataType->getTypeNameHierarchy(), "::") +
" -> " + utility::join(templateArgumentTypeNameHierarchy, "::"),
defaultArgumentType.location
);
Node* templateDefaultArgumentNode =
addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, defaultArgumentType.dataType.getTypeNameHierarchy());
addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, defaultArgumentType.dataType->getTypeNameHierarchy());
addTokenLocation(templateDefaultArgumentNode, defaultArgumentType.location);
Node* templateArgumentNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateArgumentTypeNameHierarchy);
@@ -1184,7 +1184,7 @@ Edge* Storage::addTypeEdge(Node* node, Edge::EdgeType edgeType, const ParseTypeU
return nullptr;
}
std::vector<std::string> nameHierarchy = typeUsage.dataType.getTypeNameHierarchy();
std::vector<std::string> nameHierarchy = typeUsage.dataType->getTypeNameHierarchy();
Node* typeNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, nameHierarchy);
if (!typeNode)
+1 -1
View File
@@ -1,6 +1,6 @@
#include "data/parser/ParseTypeUsage.h"
ParseTypeUsage::ParseTypeUsage(const ParseLocation& location, const DataType& dataType)
ParseTypeUsage::ParseTypeUsage(const ParseLocation& location, const std::shared_ptr<DataType> dataType)
: location(location)
, dataType(dataType)
{
+3 -2
View File
@@ -1,15 +1,16 @@
#ifndef PARSE_TYPE_USAGE_H
#define PARSE_TYPE_USAGE_H
#include <memory>
#include "data/type/DataType.h"
#include "data/parser/ParseLocation.h"
struct ParseTypeUsage
{
ParseTypeUsage(const ParseLocation& location, const DataType& dataType);
ParseTypeUsage(const ParseLocation& location, const std::shared_ptr<DataType> dataType);
const ParseLocation location;
const DataType dataType;
const std::shared_ptr<DataType> dataType;
};
#endif // PARSE_TYPE_USAGE_H
+3 -3
View File
@@ -87,7 +87,7 @@ std::string ParserClient::addLocationSuffix(
std::string ParserClient::variableStr(const ParseVariable& variable)
{
std::string str = variable.type.dataType.getFullTypeName() + " " + variable.getFullName();
std::string str = variable.type.dataType->getFullTypeName() + " " + variable.getFullName();
return addStaticPrefix(str, variable.isStatic);
}
@@ -96,7 +96,7 @@ std::string ParserClient::parameterStr(const std::vector<ParseTypeUsage> paramet
std::string str = "(";
for (size_t i = 0; i < parameters.size(); i++)
{
str += parameters[i].dataType.getFullTypeName();
str += parameters[i].dataType->getFullTypeName();
if (i < parameters.size() - 1)
{
str += ", ";
@@ -108,7 +108,7 @@ std::string ParserClient::parameterStr(const std::vector<ParseTypeUsage> paramet
std::string ParserClient::functionStr(const ParseFunction& function)
{
std::string str =
function.returnType.dataType.getFullTypeName() + " " + function.getFullName() + parameterStr(function.parameters);
function.returnType.dataType->getFullTypeName() + " " + function.getFullName() + parameterStr(function.parameters);
return addConstPrefix(addStaticPrefix(str, function.isStatic), function.isConst, false);
}
+10 -9
View File
@@ -15,6 +15,7 @@
#include "data/parser/ParseTypeUsage.h"
#include "data/parser/ParseVariable.h"
#include "data/type/DataType.h"
#include "data/type/NamedDataType.h"
ASTVisitor::ASTVisitor(clang::ASTContext* context, ParserClient* client, FileRegister* fileRegister)
: m_context(context)
@@ -79,7 +80,7 @@ bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration)
m_client->onInheritanceParsed(
getParseLocation(it.getSourceRange()),
utility::getDeclNameHierarchy(declaration),
utility::qualTypeToDataType(it.getType()).getTypeNameHierarchy(),
utility::qualTypeToDataType(it.getType())->getTypeNameHierarchy(),
convertAccessType(it.getAccessSpecifier())
);
}
@@ -299,7 +300,7 @@ bool ASTVisitor::VisitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl *
{
const clang::TemplateArgumentLoc& defaultArgumentLoc = declaration->getDefaultArgument();
clang::SourceRange sr = defaultArgumentLoc.getSourceRange();
DataType defaultArgumentDataType(utility::getDeclNameHierarchy(defaultArgumentLoc.getArgument().getAsTemplate().getAsTemplateDecl()));
std::shared_ptr<DataType> defaultArgumentDataType = std::make_shared<NamedDataType>(utility::getDeclNameHierarchy(defaultArgumentLoc.getArgument().getAsTemplate().getAsTemplateDecl()));
m_client->onTemplateDefaultArgumentTypeParsed(
getParseTypeUsage(sr, defaultArgumentDataType),
utility::getDeclNameHierarchy(declaration)
@@ -353,7 +354,7 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
const clang::TemplateArgumentList &argList = specializationDecl->getTemplateArgs();
for (size_t i = 0; i < argList.size(); i++)
{
std::vector<std::string> argumentNameHierarchy = utility::templateArgumentToDataType(argList.get(i)).getTypeNameHierarchy();
std::vector<std::string> argumentNameHierarchy = utility::templateArgumentToDataType(argList.get(i))->getTypeNameHierarchy();
if (argumentNameHierarchy.size()) // FIXME: Some TemplateArgument kinds are not handled yet.
{
@@ -403,7 +404,7 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
m_client->onTemplateArgumentTypeParsed(
getParseLocation(argumentLoc.getSourceRange()),
utility::templateArgumentToDataType(argument).getTypeNameHierarchy(),
utility::templateArgumentToDataType(argument)->getTypeNameHierarchy(),
specializedRecordNameHierarchy);
}
}
@@ -458,7 +459,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
m_client->onTemplateArgumentTypeParsed(
getParseLocation(argumentLoc.getSourceRange()),
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
utility::qualTypeToDataType(argumentType)->getTypeNameHierarchy(),
specializedFunction.nameHierarchy);
}
}
@@ -478,7 +479,7 @@ bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declarat
m_client->onTemplateArgumentTypeParsed(
ParseLocation(specializedFunctionLocation.filePath, 0, 0), // TODO: Find a valid ParseLocation here!
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
utility::qualTypeToDataType(argumentType)->getTypeNameHierarchy(),
specializedFunction.nameHierarchy);
}
}
@@ -794,11 +795,11 @@ ParseLocation ASTVisitor::getParseLocationOfRecordBody(clang::CXXRecordDecl* dec
ParseTypeUsage ASTVisitor::getParseTypeUsage(const clang::TypeLoc& typeLoc, const clang::QualType& type) const
{
DataType dataType = utility::qualTypeToDataType(type);
std::shared_ptr<DataType> dataType = utility::qualTypeToDataType(type);
return getParseTypeUsage(typeLoc, dataType);
}
ParseTypeUsage ASTVisitor::getParseTypeUsage(const clang::TypeLoc& typeLoc, const DataType& type) const
ParseTypeUsage ASTVisitor::getParseTypeUsage(const clang::TypeLoc& typeLoc, const std::shared_ptr<DataType> type) const
{
ParseLocation parseLocation;
@@ -816,7 +817,7 @@ ParseTypeUsage ASTVisitor::getParseTypeUsage(const clang::TypeLoc& typeLoc, cons
return ParseTypeUsage(parseLocation, type);
}
ParseTypeUsage ASTVisitor::getParseTypeUsage(const clang::SourceRange& sourceRange, const DataType& type) const
ParseTypeUsage ASTVisitor::getParseTypeUsage(const clang::SourceRange& sourceRange, const std::shared_ptr<DataType> type) const
{
ParseLocation parseLocation;
+2 -2
View File
@@ -71,8 +71,8 @@ private:
ParseLocation getParseLocationOfRecordBody(clang::CXXRecordDecl* decl) const;
ParseTypeUsage getParseTypeUsage(const clang::TypeLoc& typeLoc, const clang::QualType& type) const;
ParseTypeUsage getParseTypeUsage(const clang::TypeLoc& typeLoc, const DataType& type) const;
ParseTypeUsage getParseTypeUsage(const clang::SourceRange& sourceRange, const DataType& type) const;
ParseTypeUsage getParseTypeUsage(const clang::TypeLoc& typeLoc, const std::shared_ptr<DataType> type) const;
ParseTypeUsage getParseTypeUsage(const clang::SourceRange& sourceRange, const std::shared_ptr<DataType> type) const;
ParseTypeUsage getParseTypeUsageOfReturnType(const clang::FunctionDecl* declaration) const;
std::vector<ParseTypeUsage> getParameters(const clang::FunctionDecl* declaration) const;
+340 -182
View File
@@ -5,163 +5,204 @@
#include <clang/AST/ASTContext.h>
#include "data/type/DataType.h"
#include "data/type/modifier/DataTypeModifierArray.h"
#include "data/type/modifier/DataTypeModifierPointer.h"
#include "data/type/modifier/DataTypeModifierReference.h"
#include "data/type/DataTypeModifierStack.h"
#include "data/type/DataTypeQualifierList.h"
#include "data/type/NamedDataType.h"
#include "data/type/ArrayModifiedDataType.h"
#include "data/type/PointerModifiedDataType.h"
#include "data/type/ReferenceModifiedDataType.h"
#include "utility/utilityString.h"
#include "utility/logging/logging.h"
#include "llvm/Support/raw_ostream.h"
namespace utility
{
DataType qualTypeToDataType(clang::QualType qualType)
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType)
{
std::vector<std::string> typeNameHerarchy;
DataTypeQualifierList qualifierList;
DataTypeModifierStack modifierStack;
bool needsRefinement = true;
while (needsRefinement)
{
const clang::Type* type = qualType.getTypePtr();
switch (type->getTypeClass())
{
case clang::Type::Paren:
{
qualType = type->getAs<clang::ParenType>()->getInnerType();
// what about qualifiers and modifiers
break;
}
case clang::Type::Typedef:
{
typeNameHerarchy = getDeclNameHierarchy(type->getAs<clang::TypedefType>()->getDecl());
needsRefinement = false;
break;
}
case clang::Type::Pointer:
{
std::shared_ptr<DataTypeModifier> modifier = std::make_shared<DataTypeModifierPointer>();
if (qualType.isConstQualified())
{
modifier->addQualifier(DataTypeQualifierList::QUALIFIER_CONST);
}
modifierStack.push(modifier);
qualType = type->getPointeeType();
break;
}
case clang::Type::ConstantArray:
case clang::Type::VariableArray:
case clang::Type::DependentSizedArray:
case clang::Type::IncompleteArray:
{
std::shared_ptr<DataTypeModifier> modifier = std::make_shared<DataTypeModifierArray>();
if (qualType.isConstQualified())
{
modifier->addQualifier(DataTypeQualifierList::QUALIFIER_CONST);
}
modifierStack.push(modifier);
qualType = clang::dyn_cast<clang::ArrayType>(type)->getElementType();
break;
}
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
std::shared_ptr<DataTypeModifier> modifier = std::make_shared<DataTypeModifierReference>();
// references can not be const qualified
modifierStack.push(modifier);
qualType = type->getPointeeType();
break;
}
case clang::Type::Elaborated:
{
const clang::ElaboratedType* et = clang::dyn_cast<clang::ElaboratedType>(type);
qualType = et->getNamedType();
break;
}
case clang::Type::Enum:
case clang::Type::Record:
{
typeNameHerarchy = getDeclNameHierarchy(type->getAs<clang::TagType>()->getDecl());
needsRefinement = false;
break;
}
case clang::Type::Builtin:
{
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
std::string typeName = qualType.getUnqualifiedType().getAsString(pp);
typeNameHerarchy.push_back(typeName);
needsRefinement = false;
break;
}
case clang::Type::TemplateSpecialization:
{
typeNameHerarchy = getDeclNameHierarchy(type->getAs<clang::TagType>()->getDecl());
needsRefinement = false;
break;
}
case clang::Type::TemplateTypeParm:
{
clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmType>(qualType)->getDecl();
std::string typeName = getDeclName(templateTypeParmDecl);
clang::ASTContext& astContext = templateTypeParmDecl->getASTContext();
llvm::ArrayRef<clang::ast_type_traits::DynTypedNode> parents = astContext.getParents<clang::Decl>(*(clang::dyn_cast<clang::Decl>(templateTypeParmDecl)));
if (parents.size() > 0) // usually this list contains just one parent node.
{
const clang::Decl* parentNode = parents[0].get<clang::Decl>(); // use the fist parent node.
if (clang::isa<clang::NamedDecl>(parentNode))
{
const clang::NamedDecl* parentNamedDecl = clang::dyn_cast<clang::NamedDecl>(parentNode);
typeNameHerarchy = getDeclNameHierarchy(parentNamedDecl);
}
}
if (typeNameHerarchy.size() == 0)
{
LOG_ERROR("Unable to resolve type name hierarchy for template parameter \"" + typeName + "\"");
typeNameHerarchy.push_back(typeName);
}
else
{
typeNameHerarchy.back() += "::" + typeName;
}
needsRefinement = false;
break;
}
case clang::Type::SubstTemplateTypeParm:
{
const clang::SubstTemplateTypeParmType* substType = type->getAs<clang::SubstTemplateTypeParmType>();
qualType = substType->getReplacementType();
break;
}
default:
{
LOG_ERROR(std::string("Unhandled kind of type encountered: ") + type->getTypeClassName());
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
std::string typeName = qualType.getUnqualifiedType().getAsString(pp);
typeNameHerarchy.push_back(typeName);
needsRefinement = false;
break;
}
}
}
std::shared_ptr<DataType> dataType = typeToDataType(qualType.getTypePtr());
if (qualType.isConstQualified())
{
qualifierList.addQualifier(DataTypeQualifierList::QUALIFIER_CONST);
dataType->addQualifier(DataType::QUALIFIER_CONST);
}
return DataType(typeNameHerarchy, qualifierList, modifierStack);
return dataType;
}
std::shared_ptr<DataType> typeToDataType(const clang::Type* type)
{
std::shared_ptr<DataType> dataType;
switch (type->getTypeClass())
{
case clang::Type::Paren:
{
dataType = qualTypeToDataType(type->getAs<clang::ParenType>()->getInnerType());
break;
}
case clang::Type::Typedef:
{
dataType = std::make_shared<NamedDataType>(getDeclNameHierarchy(type->getAs<clang::TypedefType>()->getDecl()));
break;
}
case clang::Type::Pointer:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(type->getPointeeType());
dataType = std::make_shared<PointerModifiedDataType>(innerType);
break;
}
case clang::Type::ConstantArray:
case clang::Type::VariableArray:
case clang::Type::DependentSizedArray:
case clang::Type::IncompleteArray:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(clang::dyn_cast<clang::ArrayType>(type)->getElementType());
dataType = std::make_shared<ArrayModifiedDataType>(innerType);
break;
}
case clang::Type::LValueReference:
case clang::Type::RValueReference:
{
std::shared_ptr<DataType> innerType = qualTypeToDataType(type->getPointeeType());
dataType = std::make_shared<ReferenceModifiedDataType>(innerType);
break;
}
case clang::Type::Elaborated:
{
dataType = qualTypeToDataType(clang::dyn_cast<clang::ElaboratedType>(type)->getNamedType());
break;
}
case clang::Type::Enum:
case clang::Type::Record:
{
dataType = std::make_shared<NamedDataType>(getDeclNameHierarchy(type->getAs<clang::TagType>()->getDecl()));
break;
}
case clang::Type::Builtin:
{
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
clang::SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
clang::QualType::print(type, clang::Qualifiers(), StrOS, pp, clang::Twine());
std::string typeName = StrOS.str();
std::vector<std::string> typeNameHerarchy;
typeNameHerarchy.push_back(typeName);
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::TemplateSpecialization:
{
std::vector<std::string> typeNameHerarchy;
const clang::TagType* tagType = type->getAs<clang::TagType>(); // remove this case when NameHierarchy is split into namepart and parameter part
if (tagType)
{
typeNameHerarchy = getDeclNameHierarchy(tagType->getDecl());
}
else // specialization depends on template template parameter type
{
const clang::TemplateSpecializationType* templateSpecializationType = type->getAs<clang::TemplateSpecializationType>();
typeNameHerarchy = getDeclNameHierarchy(templateSpecializationType->getTemplateName().getAsTemplateDecl());
if (typeNameHerarchy.size() > 0)
{
std::string templateArgumentPart = "<";
for (int i = 0; i < templateSpecializationType->getNumArgs(); i++)
{
templateArgumentPart += getTemplateArgumentName(templateSpecializationType->getArg(i));
if (i < templateSpecializationType->getNumArgs() - 1)
templateArgumentPart += ", ";
}
templateArgumentPart += ">";
std::string& declName = typeNameHerarchy.back();
declName = declName.substr(0, declName.rfind("<")); // remove template parameters
declName += templateArgumentPart; // add template arguments
}
}
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::TemplateTypeParm:
{
clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmType>(type)->getDecl();
std::string typeName = getDeclName(templateTypeParmDecl);
std::vector<std::string> typeNameHerarchy = getContextNameHierarchyOfTemplateParameter(templateTypeParmDecl);
if (typeNameHerarchy.size() == 0)
{
LOG_ERROR("Unable to resolve type name hierarchy for template parameter \"" + typeName + "\"");
typeNameHerarchy.push_back(typeName);
}
else
{
typeNameHerarchy.back() += "::" + typeName;
}
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
case clang::Type::SubstTemplateTypeParm:
{
dataType = qualTypeToDataType(type->getAs<clang::SubstTemplateTypeParmType>()->getReplacementType());
break;
}
case clang::Type::DependentName:
{
const clang::DependentNameType* dependentNameType = clang::dyn_cast<clang::DependentNameType>(type);
clang::NestedNameSpecifier* nns = dependentNameType->getQualifier();
clang::NestedNameSpecifier::SpecifierKind nnsKind = nns->getKind();
std::vector<std::string> typeNameHerarchy;
switch (nnsKind)
{
case clang::NestedNameSpecifier::Identifier:
typeNameHerarchy.push_back(nns->getAsIdentifier()->getName());
LOG_ERROR("Unable to resolve name of nested name specifier of kind: Identifier"); // this one is not tested yet. tell malte if you get this log error.
break;
case clang::NestedNameSpecifier::Namespace:
typeNameHerarchy = getDeclNameHierarchy(nns->getAsNamespace());
break;
case clang::NestedNameSpecifier::NamespaceAlias:
typeNameHerarchy = getDeclNameHierarchy(nns->getAsNamespaceAlias());
break;
case clang::NestedNameSpecifier::TypeSpec:
case clang::NestedNameSpecifier::TypeSpecWithTemplate:
typeNameHerarchy = typeToDataType(nns->getAsType())->getTypeNameHierarchy();
break;
case clang::NestedNameSpecifier::Global:
// no context name hierarchy needed.
break;
case clang::NestedNameSpecifier::Super:
typeNameHerarchy = getDeclNameHierarchy(nns->getAsRecordDecl());
break;
}
typeNameHerarchy.push_back(dependentNameType->getIdentifier()->getName().str());
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
default:
{
LOG_ERROR(std::string("Unhandled kind of type encountered: ") + type->getTypeClassName());
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
clang::SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
clang::QualType::print(type, clang::Qualifiers(), StrOS, pp, clang::Twine());
std::string typeName = StrOS.str();
std::vector<std::string> typeNameHerarchy;
typeNameHerarchy.push_back(typeName);
dataType = std::make_shared<NamedDataType>(typeNameHerarchy);
break;
}
}
return dataType;
}
std::vector<std::string> getDeclNameHierarchy(const clang::Decl* declaration)
@@ -181,7 +222,8 @@ namespace utility
}
contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
if (clang::isa<clang::NonTypeTemplateParmDecl>(declaration) ||
clang::isa<clang::TemplateTypeParmDecl>(declaration)) // TODO: Handle templatetemplate stuff
clang::isa<clang::TemplateTypeParmDecl>(declaration) ||
clang::isa<clang::TemplateTemplateParmDecl>(declaration))
{
contextNameHierarchy.back() += "::" + declName;
}
@@ -214,9 +256,24 @@ namespace utility
return contextNameHierarchy;
}
std::vector<std::string> getContextNameHierarchyOfTemplateParameter(const clang::NamedDecl* templateParmDecl)
{
std::vector<std::string> contextNameHierarchy;
const clang::Decl* parentNode = getAstParentDecl(templateParmDecl);
if (parentNode && clang::isa<clang::NamedDecl>(parentNode))
{
const clang::NamedDecl* parentNamedDecl = clang::dyn_cast<clang::NamedDecl>(parentNode);
contextNameHierarchy = getDeclNameHierarchy(parentNamedDecl);
}
return contextNameHierarchy;
}
std::string getDeclName(const clang::NamedDecl* declaration)
{
std::string declName = declaration->getNameAsString();
clang::Decl::Kind kind = declaration->getKind();
if (clang::isa<clang::CXXRecordDecl>(declaration))
{
clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(declaration)->getDescribedClassTemplate();
@@ -234,10 +291,10 @@ namespace utility
std::string specializedParameterNamePart = "<";
int templateArgumentCount = partialSpecializationDecl->getTemplateArgs().size();
const clang::ASTTemplateArgumentListInfo* templateArgumentListInfo = partialSpecializationDecl->getTemplateArgsAsWritten();
const clang::TemplateArgumentList& templateArgumentList = partialSpecializationDecl->getTemplateArgs();
for (int i = 0; i < templateArgumentCount; i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentListInfo->getTemplateArgs()[i].getArgument();
const clang::TemplateArgument& templateArgument = templateArgumentList.get(i);
if (templateArgument.isDependent()) // TODO: fix case when arg depends on template parameter of outer template class.
{
specializedParameterNamePart += getTemplateParameterString(parameterList->getParam(currentParameterIndex));
@@ -279,18 +336,14 @@ namespace utility
for (size_t i = 0; i < templateArgumentList->size(); i++)
{
const clang::TemplateArgument& templateArgument = templateArgumentList->get(i);
specializedParameterNamePart += templateArgumentToDataType(templateArgument).getFullTypeName();
specializedParameterNamePart += templateArgumentToDataType(templateArgument)->getFullTypeName();
specializedParameterNamePart += (i < templateArgumentList->size() - 1) ? ", " : "";
}
specializedParameterNamePart += ">";
declName += specializedParameterNamePart;
}
}
else if (clang::isa<clang::TemplateTemplateParmDecl>(declaration))
{
// nothing to do here
}
else if (clang::isa<clang::TemplateDecl>(declaration))
else if (clang::isa<clang::TemplateDecl>(declaration)) // also triggers on TemplateTemplateParmDecl
{
std::string templateParameterNamePart = "<";
clang::TemplateParameterList* parameterList = clang::dyn_cast<clang::TemplateDecl>(declaration)->getTemplateParameters();
@@ -328,7 +381,7 @@ namespace utility
return specializationParentNameHierarchy;
}
DataType templateArgumentToDataType(const clang::TemplateArgument& argument) // remove this! this is stupid! agurment is not always a datatype.
std::shared_ptr<DataType> templateArgumentToDataType(const clang::TemplateArgument& argument) // remove this! this is stupid! agurment is not always a datatype.
{
const clang::TemplateArgument::ArgKind kind = argument.getKind();
switch (kind)
@@ -348,12 +401,15 @@ namespace utility
case clang::TemplateArgument::Template:
{
clang::TemplateName templateName = argument.getAsTemplate();
clang::TemplateName::NameKind::Template;
switch (templateName.getKind())
{
case clang::TemplateName::Template:
return DataType(getDeclNameHierarchy(templateName.getAsTemplateDecl()));
return std::make_shared<NamedDataType>(getDeclNameHierarchy(templateName.getAsTemplateDecl()));
break;
default:
LOG_ERROR("Type of template argument not handled: Template");
}
LOG_ERROR("Type of template argument not handled: Template");
}
break;
case clang::TemplateArgument::TemplateExpansion:
@@ -368,40 +424,24 @@ namespace utility
LOG_ERROR("Type of template argument not handled." + argument.getKind());
break;
}
return DataType(std::vector<std::string>());
return std::make_shared<NamedDataType>(std::vector<std::string>());
}
std::string getTemplateParameterString(const clang::NamedDecl* parameter)
{
std::string templateParameterString = "";
clang::Decl::Kind templateParameterKind = parameter->getKind();
switch (templateParameterKind)
{
case clang::Decl::NonTypeTemplateParm:
{
const clang::NonTypeTemplateParmDecl* nonTypeTemplateParmDecl = clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter);
templateParameterString = qualTypeToDataType(nonTypeTemplateParmDecl->getType()).getFullTypeName();
}
templateParameterString = getTemplateParameterTypeString(clang::dyn_cast<clang::NonTypeTemplateParmDecl>(parameter));
break;
case clang::Decl::TemplateTypeParm:
{
const clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter);
templateParameterString = templateTypeParmDecl->wasDeclaredWithTypename() ? "typename" : "class";
}
templateParameterString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTypeParmDecl>(parameter));
break;
case clang::Decl::TemplateTemplateParm:
{
const clang::TemplateTemplateParmDecl* templateTemplateParmDecl = clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter);
templateParameterString = "template<";
clang::TemplateParameterList* parameterList = templateTemplateParmDecl->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterString += getTemplateParameterString(parameterList->getParam(i));
templateParameterString += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterString += ">";
templateParameterString += " typename"; // TODO: what if template template parameter is defined with class keyword?
}
templateParameterString = getTemplateParameterTypeString(clang::dyn_cast<clang::TemplateTemplateParmDecl>(parameter));
break;
default:
LOG_ERROR("Unhandled kind of template parameter.");
@@ -415,13 +455,102 @@ namespace utility
return templateParameterString;
}
std::string getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter)
{
std::string templateParameterTypeString = "";
const clang::QualType parmeterType = parameter->getType();
clang::Type::TypeClass parmeterTypeClass = parmeterType->getTypeClass();
if (parmeterTypeClass == clang::Type::TemplateTypeParm)
{
clang::TemplateTypeParmDecl* parmeterTypeDecl = clang::dyn_cast<clang::TemplateTypeParmType>(parmeterType)->getDecl();
if (haveAstAncestorRelation(getAstParentDecl(parameter), parmeterTypeDecl))
{
templateParameterTypeString = getDeclName(parmeterTypeDecl);
}
}
else if (parmeterTypeClass == clang::Type::DependentName)
{
clang::NestedNameSpecifier* nns = clang::dyn_cast<clang::DependentNameType>(parmeterType)->getQualifier();
clang::NamedDecl* typeParent;
switch (nns->getKind())
{
case clang::NestedNameSpecifier::Identifier:
{
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
templateParameterTypeString = parmeterType.getAsString(pp);
}
break;
case clang::NestedNameSpecifier::Namespace:
typeParent = nns->getAsNamespace();
break;
case clang::NestedNameSpecifier::NamespaceAlias:
typeParent = nns->getAsNamespaceAlias();
break;
case clang::NestedNameSpecifier::TypeSpec:
case clang::NestedNameSpecifier::TypeSpecWithTemplate:
{
const clang::Type* ssswd = nns->getAsType();
clang::Type::TypeClass szz = ssswd->getTypeClass();
switch (ssswd->getTypeClass())
{
case clang::Type::TemplateTypeParm:
typeParent = clang::dyn_cast<clang::TemplateTypeParmType>(ssswd)->getDecl();
break;
default:
LOG_ERROR("aahhh");
}
}
break;
case clang::NestedNameSpecifier::Global:
typeParent = nullptr;
break;
case clang::NestedNameSpecifier::Super:
typeParent = nns->getAsRecordDecl();
break;
}
if (typeParent && haveAstAncestorRelation(getAstParentDecl(parameter), typeParent))
{
templateParameterTypeString = getDeclName(typeParent);
templateParameterTypeString += "::" + clang::dyn_cast<clang::DependentNameType>(parmeterType)->getIdentifier()->getName().str();
}
}
if (templateParameterTypeString.empty()) // this is the default case
{
templateParameterTypeString = qualTypeToDataType(parmeterType)->getFullTypeName();
}
return templateParameterTypeString;
}
std::string getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter)
{
return (parameter->wasDeclaredWithTypename() ? "typename" : "class");
}
std::string getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter)
{
std::string templateParameterTypeString = "template<";
clang::TemplateParameterList* parameterList = parameter->getTemplateParameters();
for (size_t i = 0; i < parameterList->size(); i++)
{
templateParameterTypeString += getTemplateParameterString(parameterList->getParam(i));
templateParameterTypeString += (i < parameterList->size() - 1) ? ", " : "";
}
templateParameterTypeString += ">";
templateParameterTypeString += " typename"; // TODO: what if template template parameter is defined with class keyword?
return templateParameterTypeString;
}
std::string getTemplateArgumentName(const clang::TemplateArgument& argument)
{
const clang::TemplateArgument::ArgKind kind = argument.getKind();
switch (kind)
{
case clang::TemplateArgument::Type:
return utility::qualTypeToDataType(argument.getAsType()).getFullTypeName();
return utility::qualTypeToDataType(argument.getAsType())->getFullTypeName();
case clang::TemplateArgument::Integral:
case clang::TemplateArgument::Null:
case clang::TemplateArgument::Declaration:
@@ -448,4 +577,33 @@ namespace utility
}
return std::string();
}
bool haveAstAncestorRelation(const clang::Decl* parent, const clang::Decl* child)
{
if (parent)
{
while (child)
{
if (parent == child)
{
return true;
}
child = getAstParentDecl(child);
}
}
return false;
}
const clang::Decl* getAstParentDecl(const clang::Decl* decl)
{
clang::ASTContext& astContext = decl->getASTContext();
llvm::ArrayRef<clang::ast_type_traits::DynTypedNode> parents = astContext.getParents<clang::Decl>(*(decl));
if (parents.size() > 0) // usually this list contains just one parent node.
{
return parents[0].get<clang::Decl>(); // use the fist parent node.
}
return nullptr;
}
}
+10 -2
View File
@@ -13,15 +13,23 @@ class DataType;
namespace utility
{
DataType qualTypeToDataType(clang::QualType qualType);
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType);
std::shared_ptr<DataType> typeToDataType(const clang::Type* type);
std::vector<std::string> getDeclNameHierarchy(const clang::Decl* declaration);
std::vector<std::string> getContextNameHierarchy(const clang::DeclContext* declaration);
std::vector<std::string> getContextNameHierarchyOfTemplateParameter(const clang::NamedDecl* templateParmDecl);
std::string getDeclName(const clang::NamedDecl* declaration);
std::vector<std::string> getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration);
DataType templateArgumentToDataType(const clang::TemplateArgument& argument);
std::shared_ptr<DataType> templateArgumentToDataType(const clang::TemplateArgument& argument);
std::string getTemplateParameterString(const clang::NamedDecl* parameter);
std::string getTemplateParameterTypeString(const clang::NonTypeTemplateParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTypeParmDecl* parameter);
std::string getTemplateParameterTypeString(const clang::TemplateTemplateParmDecl* parameter);
std::string getTemplateArgumentName(const clang::TemplateArgument& argument);
bool haveAstAncestorRelation(const clang::Decl* parent, const clang::Decl* child);
const clang::Decl* getAstParentDecl(const clang::Decl* decl);
}
#endif // UTILITY_CLANG_H
@@ -0,0 +1,15 @@
#include "data/type/ArrayModifiedDataType.h"
ArrayModifiedDataType::ArrayModifiedDataType(std::shared_ptr<DataType> dataType)
: ModifiedDataType(dataType)
{
}
ArrayModifiedDataType::~ArrayModifiedDataType()
{
}
void ArrayModifiedDataType::applyModifier(std::string& typeName) const
{
typeName.append(" []");
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef ARRAY_MODIFIED_DATA_TYPE_H
#define ARRAY_MODIFIED_DATA_TYPE_H
#include "ModifiedDataType.h"
class ArrayModifiedDataType: public ModifiedDataType
{
public:
ArrayModifiedDataType(std::shared_ptr<DataType> dataType);
virtual ~ArrayModifiedDataType();
protected:
virtual void applyModifier(std::string& typeName) const;
};
#endif // ARRAY_MODIFIED_DATA_TYPE_H
+14 -34
View File
@@ -1,25 +1,7 @@
#include "data/type/DataType.h"
#include "utility/utilityString.h"
DataType::DataType(const std::vector<std::string>& typeNameHierarchy)
: m_typeNameHierarchy(typeNameHierarchy)
{
}
DataType::DataType(const std::vector<std::string>& typeNameHierarchy, const DataTypeQualifierList& qualifierList)
: m_typeNameHierarchy(typeNameHierarchy)
, m_qualifierList(qualifierList)
{
}
DataType::DataType(
const std::vector<std::string>& typeNameHierarchy, const DataTypeQualifierList& qualifierList,
const DataTypeModifierStack& modifierStack
)
: m_typeNameHierarchy(typeNameHierarchy)
, m_qualifierList(qualifierList)
, m_modifierStack(modifierStack)
DataType::DataType()
: m_qualifiers(QUALIFIER_NONE)
{
}
@@ -27,27 +9,25 @@ DataType::~DataType()
{
}
DataTypeQualifierList DataType::getQualifierList() const
void DataType::addQualifier(QualifierType qualifier)
{
return m_qualifierList;
m_qualifiers = m_qualifiers | qualifier;
}
DataTypeModifierStack DataType::getModifierStack() const
void DataType::removeQualifier(QualifierType qualifier)
{
return m_modifierStack;
m_qualifiers = m_qualifiers & ~qualifier;
}
std::string DataType::getFullTypeName() const
bool DataType::hasQualifier(QualifierType qualifier) const
{
return m_modifierStack.applyTo(m_qualifierList.applyTo(getRawTypeName()));
return (m_qualifiers & qualifier) > 0;
}
std::string DataType::getRawTypeName() const
void DataType::applyQualifieres(std::string& typeName) const
{
return utility::join(m_typeNameHierarchy, "::");
}
const std::vector<std::string>& DataType::getTypeNameHierarchy() const
{
return m_typeNameHierarchy;
}
if (hasQualifier(QUALIFIER_CONST))
{
typeName += " const";
}
}
+19 -19
View File
@@ -1,34 +1,34 @@
#ifndef DATA_TYPE_H
#define DATA_TYPE_H
#include <memory>
#include <string>
#include "data/type/DataTypeModifierStack.h"
#include "data/type/DataTypeQualifierList.h"
#include <vector>
class DataType
{
public:
DataType(const std::vector<std::string>& typeNameHierarchy);
DataType(const std::vector<std::string>& typeNameHierarchy, const DataTypeQualifierList& qualifierList);
DataType(
const std::vector<std::string>& typeNameHierarchy, const DataTypeQualifierList& qualifierList,
const DataTypeModifierStack& modifierStack
);
~DataType();
enum QualifierType
{
QUALIFIER_NONE = 0,
QUALIFIER_CONST = 1
};
DataTypeQualifierList getQualifierList() const;
DataTypeModifierStack getModifierStack() const;
DataType();
virtual ~DataType();
std::string getFullTypeName() const;
std::string getRawTypeName() const;
const std::vector<std::string>& getTypeNameHierarchy() const;
virtual std::string getFullTypeName() const = 0;
virtual std::string getRawTypeName() const = 0;
virtual const std::vector<std::string>& getTypeNameHierarchy() const = 0;
void addQualifier(QualifierType qualifier);
void removeQualifier(QualifierType qualifier);
bool hasQualifier(QualifierType qualifier) const;
protected:
void applyQualifieres(std::string& typeName) const;
private:
const std::vector<std::string> m_typeNameHierarchy;
const DataTypeQualifierList m_qualifierList;
const DataTypeModifierStack m_modifierStack;
char m_qualifiers;
};
#endif // DATA_TYPE_H
@@ -1,46 +0,0 @@
#include "data/type/DataTypeModifierStack.h"
DataTypeModifierStack::DataTypeModifierStack()
{
}
DataTypeModifierStack::DataTypeModifierStack(const DataTypeModifierStack& o)
{
for (std::shared_ptr<DataTypeModifier> modifier: o.m_modifiers)
{
m_modifiers.push_back(modifier->copy());
}
}
DataTypeModifierStack& DataTypeModifierStack::operator=(const DataTypeModifierStack &o)
{
if (this != &o)
{
m_modifiers.clear();
for (std::shared_ptr<DataTypeModifier> modifier: o.m_modifiers)
{
m_modifiers.push_back(modifier->copy());
}
}
return *this;
}
DataTypeModifierStack::~DataTypeModifierStack()
{
}
void DataTypeModifierStack::push(std::shared_ptr<DataTypeModifier> modifier)
{
m_modifiers.push_back(modifier);
}
std::string DataTypeModifierStack::applyTo(const std::string& typeName) const
{
typedef std::vector<std::shared_ptr<DataTypeModifier>>::const_reverse_iterator StackIterator;
std::string modifiedTypeName = typeName;
for (StackIterator it = m_modifiers.rbegin(); it != m_modifiers.rend(); it++)
{
(*it)->applyTo(modifiedTypeName);
}
return modifiedTypeName;
}
-27
View File
@@ -1,27 +0,0 @@
#ifndef DATA_TYPE_MODIFIER_STACK_H
#define DATA_TYPE_MODIFIER_STACK_H
#include <memory>
#include <string>
#include <vector>
#include "data/type/modifier/DataTypeModifier.h"
class DataTypeModifierStack
{
public:
DataTypeModifierStack();
DataTypeModifierStack(const DataTypeModifierStack& o);
DataTypeModifierStack& operator=(const DataTypeModifierStack &o);
~DataTypeModifierStack();
void push(std::shared_ptr<DataTypeModifier> modifier);
std::string applyTo(const std::string& typeName) const;
private:
std::vector<std::shared_ptr<DataTypeModifier>> m_modifiers;
};
#endif // DATA_TYPE_MODIFIER_STACK_H
@@ -1,35 +0,0 @@
#include "data/type/DataTypeQualifierList.h"
DataTypeQualifierList::DataTypeQualifierList()
: m_qualifiers(QUALIFIER_NONE)
{
}
DataTypeQualifierList::~DataTypeQualifierList()
{
}
void DataTypeQualifierList::addQualifier(QualifierType qualifier)
{
m_qualifiers = m_qualifiers | qualifier;
}
void DataTypeQualifierList::removeQualifier(QualifierType qualifier)
{
m_qualifiers = m_qualifiers & ~qualifier;
}
bool DataTypeQualifierList::hasQualifier(QualifierType qualifier) const
{
return (m_qualifiers & qualifier) > 0;
}
std::string DataTypeQualifierList::applyTo(const std::string& typeName) const
{
std::string qualifiedTypeName = typeName;
if (hasQualifier(QUALIFIER_CONST))
{
qualifiedTypeName += " const";
}
return qualifiedTypeName;
}
-29
View File
@@ -1,29 +0,0 @@
#ifndef DATA_TYPE_QUALIFIER_H
#define DATA_TYPE_QUALIFIER_H
#include <memory>
#include <string>
class DataTypeQualifierList
{
public:
enum QualifierType
{
QUALIFIER_NONE = 0,
QUALIFIER_CONST = 1
};
DataTypeQualifierList();
~DataTypeQualifierList();
void addQualifier(QualifierType qualifier);
void removeQualifier(QualifierType qualifier);
bool hasQualifier(QualifierType qualifier) const;
std::string applyTo(const std::string& typeName) const;
private:
char m_qualifiers;
};
#endif // DATA_TYPE_H
+28
View File
@@ -0,0 +1,28 @@
#include "data/type/ModifiedDataType.h"
ModifiedDataType::ModifiedDataType(std::shared_ptr<DataType> dataType)
: m_dataType(dataType)
{
}
ModifiedDataType::~ModifiedDataType()
{
}
std::string ModifiedDataType::getFullTypeName() const
{
std::string fullTypeName = m_dataType->getFullTypeName();
applyModifier(fullTypeName);
applyQualifieres(fullTypeName);
return fullTypeName;
}
std::string ModifiedDataType::getRawTypeName() const
{
return m_dataType->getRawTypeName();
}
const std::vector<std::string>& ModifiedDataType::getTypeNameHierarchy() const
{
return m_dataType->getTypeNameHierarchy();
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef MODIFIED_DATA_TYPE_H
#define MODIFIED_DATA_TYPE_H
#include <memory>
#include "DataType.h"
class ModifiedDataType: public DataType
{
public:
ModifiedDataType(std::shared_ptr<DataType> dataType);
virtual ~ModifiedDataType();
virtual std::string getFullTypeName() const;
virtual std::string getRawTypeName() const;
virtual const std::vector<std::string>& getTypeNameHierarchy() const;
protected:
virtual void applyModifier(std::string& typeName) const = 0;
private:
const std::shared_ptr<DataType> m_dataType;
};
#endif // MODIFIED_DATA_TYPE_H
+29
View File
@@ -0,0 +1,29 @@
#include "data/type/NamedDataType.h"
#include "utility/utilityString.h"
NamedDataType::NamedDataType(const std::vector<std::string>& nameHierarchy)
: m_nameHierarchy(nameHierarchy)
{
}
NamedDataType::~NamedDataType()
{
}
std::string NamedDataType::getFullTypeName() const
{
std::string fullTypeName = getRawTypeName();
applyQualifieres(fullTypeName);
return fullTypeName;
}
std::string NamedDataType::getRawTypeName() const
{
return utility::join(m_nameHierarchy, "::");
}
const std::vector<std::string>& NamedDataType::getTypeNameHierarchy() const
{
return m_nameHierarchy;
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef NAMED_DATA_TYPE_H
#define NAMED_DATA_TYPE_H
#include "DataType.h"
class NamedDataType: public DataType
{
public:
NamedDataType(const std::vector<std::string>& nameHierarchy);
virtual ~NamedDataType();
virtual std::string getFullTypeName() const;
virtual std::string getRawTypeName() const;
virtual const std::vector<std::string>& getTypeNameHierarchy() const;
private:
const std::vector<std::string> m_nameHierarchy;
};
#endif // NAMED_DATA_TYPE_H
@@ -0,0 +1,15 @@
#include "data/type/PointerModifiedDataType.h"
PointerModifiedDataType::PointerModifiedDataType(std::shared_ptr<DataType> dataType)
: ModifiedDataType(dataType)
{
}
PointerModifiedDataType::~PointerModifiedDataType()
{
}
void PointerModifiedDataType::applyModifier(std::string& typeName) const
{
typeName.append(" *");
}
@@ -0,0 +1,16 @@
#ifndef POINTER_MODIFIED_DATA_TYPE_H
#define POINTER_MODIFIED_DATA_TYPE_H
#include "ModifiedDataType.h"
class PointerModifiedDataType: public ModifiedDataType
{
public:
PointerModifiedDataType(std::shared_ptr<DataType> dataType);
virtual ~PointerModifiedDataType();
protected:
virtual void applyModifier(std::string& typeName) const;
};
#endif // POINTER_MODIFIED_DATA_TYPE_H
@@ -0,0 +1,15 @@
#include "data/type/ReferenceModifiedDataType.h"
ReferenceModifiedDataType::ReferenceModifiedDataType(std::shared_ptr<DataType> dataType)
: ModifiedDataType(dataType)
{
}
ReferenceModifiedDataType::~ReferenceModifiedDataType()
{
}
void ReferenceModifiedDataType::applyModifier(std::string& typeName) const
{
typeName.append(" &");
}
@@ -0,0 +1,16 @@
#ifndef REFERENCE_MODIFIED_DATA_TYPE_H
#define REFERENCE_MODIFIED_DATA_TYPE_H
#include "ModifiedDataType.h"
class ReferenceModifiedDataType: public ModifiedDataType
{
public:
ReferenceModifiedDataType(std::shared_ptr<DataType> dataType);
virtual ~ReferenceModifiedDataType();
protected:
virtual void applyModifier(std::string& typeName) const;
};
#endif // REFERENCE_MODIFIED_DATA_TYPE_H
@@ -1,37 +0,0 @@
#include "data/type/modifier/DataTypeModifier.h"
DataTypeModifier::DataTypeModifier()
{
}
DataTypeModifier::~DataTypeModifier()
{
}
std::shared_ptr<DataTypeModifier> DataTypeModifier::copy() const
{
std::shared_ptr<DataTypeModifier> copy = doCopy();
copy->m_qualifierList = m_qualifierList;
return copy;
}
void DataTypeModifier::applyTo(std::string& typeName) const
{
doApplyTo(typeName);
typeName = m_qualifierList.applyTo(typeName);
}
void DataTypeModifier::addQualifier(DataTypeQualifierList::QualifierType qualifier)
{
m_qualifierList.addQualifier(qualifier);
}
void DataTypeModifier::removeQualifier(DataTypeQualifierList::QualifierType qualifier)
{
m_qualifierList.removeQualifier(qualifier);
}
bool DataTypeModifier::hasQualifier(DataTypeQualifierList::QualifierType qualifier) const
{
return m_qualifierList.hasQualifier(qualifier);
}
@@ -1,29 +0,0 @@
#ifndef DATA_TYPE_MODIFIER_H
#define DATA_TYPE_MODIFIER_H
#include <string>
#include "data/type/DataTypeQualifierList.h"
class DataTypeModifier
{
public:
DataTypeModifier();
virtual ~DataTypeModifier();
std::shared_ptr<DataTypeModifier> copy() const;
void applyTo(std::string& typeName) const;
void addQualifier(DataTypeQualifierList::QualifierType qualifier);
void removeQualifier(DataTypeQualifierList::QualifierType qualifier);
bool hasQualifier(DataTypeQualifierList::QualifierType qualifier) const;
private:
virtual std::shared_ptr<DataTypeModifier> doCopy() const = 0;
virtual void doApplyTo(std::string& typeName) const = 0;
DataTypeQualifierList m_qualifierList;
};
#endif // DATA_TYPE_MODIFIER_H
@@ -1,19 +0,0 @@
#include "data/type/modifier/DataTypeModifierArray.h"
DataTypeModifierArray::DataTypeModifierArray()
{
}
DataTypeModifierArray::~DataTypeModifierArray()
{
}
std::shared_ptr<DataTypeModifier> DataTypeModifierArray::doCopy() const
{
return std::make_shared<DataTypeModifierArray>();
}
void DataTypeModifierArray::doApplyTo(std::string& typeName) const
{
typeName.append(" []");
}
@@ -1,17 +0,0 @@
#ifndef DATA_TYPE_MODIFIER_ARRAY_H
#define DATA_TYPE_MODIFIER_ARRAY_H
#include "data/type/modifier/DataTypeModifier.h"
class DataTypeModifierArray: public DataTypeModifier
{
public:
DataTypeModifierArray();
virtual ~DataTypeModifierArray();
private:
virtual std::shared_ptr<DataTypeModifier> doCopy() const;
virtual void doApplyTo(std::string& typeName) const;
};
#endif // DATA_TYPE_MODIFIER_ARRAY_H
@@ -1,19 +0,0 @@
#include "data/type/modifier/DataTypeModifierPointer.h"
DataTypeModifierPointer::DataTypeModifierPointer()
{
}
DataTypeModifierPointer::~DataTypeModifierPointer()
{
}
std::shared_ptr<DataTypeModifier> DataTypeModifierPointer::doCopy() const
{
return std::make_shared<DataTypeModifierPointer>();
}
void DataTypeModifierPointer::doApplyTo(std::string& typeName) const
{
typeName.append(" *");
}
@@ -1,17 +0,0 @@
#ifndef DATA_TYPE_MODIFIER_POINTER_H
#define DATA_TYPE_MODIFIER_POINTER_H
#include "data/type/modifier/DataTypeModifier.h"
class DataTypeModifierPointer: public DataTypeModifier
{
public:
DataTypeModifierPointer();
virtual ~DataTypeModifierPointer();
private:
virtual std::shared_ptr<DataTypeModifier> doCopy() const;
virtual void doApplyTo(std::string& typeName) const;
};
#endif // DATA_TYPE_MODIFIER_POINTER_H
@@ -1,19 +0,0 @@
#include "data/type/modifier/DataTypeModifierReference.h"
DataTypeModifierReference::DataTypeModifierReference()
{
}
DataTypeModifierReference::~DataTypeModifierReference()
{
}
std::shared_ptr<DataTypeModifier> DataTypeModifierReference::doCopy() const
{
return std::make_shared<DataTypeModifierReference>();
}
void DataTypeModifierReference::doApplyTo(std::string& typeName) const
{
typeName.append(" &");
}
@@ -1,17 +0,0 @@
#ifndef DATA_TYPE_MODIFIER_REFERENCE_H
#define DATA_TYPE_MODIFIER_REFERENCE_H
#include "data/type/modifier/DataTypeModifier.h"
class DataTypeModifierReference: public DataTypeModifier
{
public:
DataTypeModifierReference();
virtual ~DataTypeModifierReference();
private:
virtual std::shared_ptr<DataTypeModifier> doCopy() const;
virtual void doApplyTo(std::string& typeName) const;
};
#endif // DATA_TYPE_MODIFIER_REFERENCE_H
+120 -10
View File
@@ -1311,9 +1311,119 @@ public:
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2);
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<typename T>::T <1:20 1:20>");
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "B<template<typename> typename T>::T <4:36 4:36>");
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "B<template<typename> typename T>::T<typename> <4:36 4:36>");
}
void test_cxx_parser_finds_usage_of_template_template_parameter_of_template_class_specialized_with_concrete_type()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
"class A\n"
"{};\n"
"template <template<typename> class T>\n"
"class B\n"
"{\n"
" void foo(T<int> parameter)\n"
" {}\n"
"};\n"
);
TS_ASSERT_EQUALS(client->typeUses.size(), 2);
TS_ASSERT_EQUALS(client->typeUses[0], "void <7:2 7:5>");
TS_ASSERT_EQUALS(client->typeUses[1], "B<template<typename> typename T>::T<int> <7:11 7:16>");
}
void test_cxx_parser_finds_usage_of_template_template_parameter_of_template_class_specialized_with_template_type()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
"class A\n"
"{};\n"
"template <template<typename> class T>\n"
"class B\n"
"{\n"
" template <typename U> \n"
" void foo(T<U> parameter)\n"
" {}\n"
"};\n"
);
TS_ASSERT_EQUALS(client->typeUses.size(), 2);
TS_ASSERT_EQUALS(client->typeUses[0], "void <8:2 8:5>");
TS_ASSERT_EQUALS(client->typeUses[1], "B<template<typename> typename T>::T<B<template<typename> typename T>::foo<typename U>::U> <8:11 8:14>");
}
void test_cxx_parser_finds_usage_of_template_template_parameter_of_template_class_specialized_with_template_type00000000000666666666666()
{
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T>\n"
"class A\n"
"{\n"
"public:"
" typedef T type;\n"
"};\n"
"template <typename U>\n"
"class B\n"
"{\n"
"public:"
" typedef typename A<U>::type type;\n"
"};\n"
"B<int>::type f = 0;\n"
);
TS_ASSERT_EQUALS(client->typedefs.size(), 2);
TS_ASSERT_EQUALS(client->typedefs[0], "public A<typename T>::T -> A<typename T>::type <4:19 4:22>");
TS_ASSERT_EQUALS(client->typedefs[1], "public A<B<typename U>::U>::type -> B<typename U>::type <9:37 9:40>");
}
void test_cxx_parser_finds_usage_of_template_template_parameter_of_template_class_specialized_with_template_type00ss000666666666666()
{
int zz1 = 0;
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, T test>\n"
"class A\n"
"{\n"
"};\n"
);
int zz2 = 0;
TS_ASSERT_EQUALS(client->classes.size(), 1);
TS_ASSERT_EQUALS(client->classes[0], "A<typename T, T test> <2:1 <2:7 2:7> 4:1>");
}
void test_cxx_parser_finds_usage_of_template_template_parameter_of_template_class_specialized_with_template_type00sstt000666666666666()
{
int zz1 = 0;
std::shared_ptr<TestParserClient> client = parseCode(
"template <typename T, typename T::type test>\n"
"class A\n"
"{\n"
"};\n"
);
int zz2 = 0;
}
void test_cxx_parser_finds_type_template_parameters_of_template_class_with_multiple_parameters()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -1725,8 +1835,8 @@ public:
);
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<p, P & q>->P <8:9 8:9>");
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<p, P & q>->P <8:12 8:12>");
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&p, P & q>->P <8:9 8:9>"); // why reference here?
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<&p, P & q>->P <8:12 8:12>");
}
void test_cxx_parser_finds_non_type_nullptr_template_argument_of_explicit_partial_template_specialization()
@@ -1764,7 +1874,7 @@ public:
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<A, template<typename> typename U>->A<typename T> <8:9 8:9>");
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "B<A, template<typename> typename U>->B<A, template<typename> typename U>::U <8:12 8:12>");
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "B<A, template<typename> typename U>->B<A, template<typename> typename U>::U<typename> <8:12 8:12>");
}
void test_cxx_parser_finds_correct_name_of_explicit_template_specialization()
@@ -2033,7 +2143,7 @@ public:
);
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1);
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "A<typename T> -> B<template<typename> typename T>::T <4:40 4:40>");
TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "A<typename T> -> B<template<typename> typename T>::T<typename> <4:40 4:40>");
}
@@ -2142,7 +2252,7 @@ public:
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2);
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<typename T>::T <1:20 1:20>");
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "test<template<typename> typename T>::T <4:36 4:36>");
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "test<template<typename> typename T>::T<typename> <4:36 4:36>");
}
void test_cxx_parser_finds_implicit_specialization_of_template_function()
@@ -2297,7 +2407,7 @@ private:
AccessType access
)
{
std::string str = addAccessPrefix(underlyingType.dataType.getFullTypeName() + " -> " + utility::join(nameHierarchy, "::"), access);
std::string str = addAccessPrefix(underlyingType.dataType->getFullTypeName() + " -> " + utility::join(nameHierarchy, "::"), access);
typedefs.push_back(addLocationSuffix(str, location));
return 0;
}
@@ -2471,7 +2581,7 @@ private:
const ParseTypeUsage& defaultArgumentType, const std::vector<std::string>& templateArgumentTypeNameHierarchy)
{
templateDefaultArgumentTypes.push_back(
addLocationSuffix(utility::join(defaultArgumentType.dataType.getTypeNameHierarchy(), "::") + " -> " + utility::join(templateArgumentTypeNameHierarchy, "::"), defaultArgumentType.location)
addLocationSuffix(utility::join(defaultArgumentType.dataType->getTypeNameHierarchy(), "::") + " -> " + utility::join(templateArgumentTypeNameHierarchy, "::"), defaultArgumentType.location)
);
return 0;
}
@@ -2560,7 +2670,7 @@ private:
{
if (use.location.isValid())
{
typeUses.push_back(addLocationSuffix(use.dataType.getFullTypeName(), use.location));
typeUses.push_back(addLocationSuffix(use.dataType->getFullTypeName(), use.location));
}
}
@@ -2569,7 +2679,7 @@ private:
if (use.location.isValid())
{
typeUses.push_back(
addLocationSuffix(functionStr(func) + " -> " + use.dataType.getFullTypeName(), use.location)
addLocationSuffix(functionStr(func) + " -> " + use.dataType->getFullTypeName(), use.location)
);
}
}
+31 -49
View File
@@ -3,87 +3,69 @@
#include "utility/utilityString.h"
#include "data/type/DataType.h"
#include "data/type/modifier/DataTypeModifierArray.h"
#include "data/type/modifier/DataTypeModifierPointer.h"
#include "data/type/modifier/DataTypeModifierReference.h"
#include "data/type/NamedDataType.h"
#include "data/type/ArrayModifiedDataType.h"
#include "data/type/PointerModifiedDataType.h"
#include "data/type/ReferenceModifiedDataType.h"
class DataTypeTestSuite: public CxxTest::TestSuite
{
public:
void test_datatype_created_with_name_has_no_qualifiers_or_modifiers()
{
DataType dataType(utility::splitToVector("int", "::"));
TS_ASSERT_EQUALS("int", dataType.getFullTypeName());
}
void test_datatype_created_with_name_and_empty_qualifiers_has_no_qualifiers_or_modifiers()
{
DataTypeQualifierList qualifierList;
DataType dataType(utility::splitToVector("int", "::"), qualifierList);
NamedDataType dataType(utility::splitToVector("int", "::"));
TS_ASSERT_EQUALS("int", dataType.getFullTypeName());
}
void test_datatype_created_with_name_and_const_qualifier_has_no_modifiers()
{
DataTypeQualifierList qualifierList;
qualifierList.addQualifier(DataTypeQualifierList::QUALIFIER_CONST);
DataType dataType(utility::splitToVector("int", "::"), qualifierList);
NamedDataType dataType(utility::splitToVector("int", "::"));
dataType.addQualifier(DataType::QUALIFIER_CONST);
TS_ASSERT_EQUALS("int const", dataType.getFullTypeName());
}
void test_datatype_created_with_name_and_empty_modifierstack_has_no_modifiers()
{
DataTypeQualifierList qualifierList;
DataTypeModifierStack modifierStack;
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
TS_ASSERT_EQUALS("int", dataType.getFullTypeName());
}
//void __test_datatype_created_with_name_and_empty_modifierstack_has_no_modifiers()
//{
// DataTypeQualifierList qualifierList;
// DataTypeModifierStack modifierStack;
// DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
// TS_ASSERT_EQUALS("int", dataType.getFullTypeName());
//}
void test_datatype_created_with_name_and_array_modifier_has_array_modifier()
{
DataTypeQualifierList qualifierList;
DataTypeModifierStack modifierStack;
modifierStack.push(std::make_shared<DataTypeModifierArray>());
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
TS_ASSERT_EQUALS("int []", dataType.getFullTypeName());
std::shared_ptr<DataType> dataType1 = std::make_shared<NamedDataType>(utility::splitToVector("int", "::"));
std::shared_ptr<DataType> dataType2 = std::make_shared<ArrayModifiedDataType>(dataType1);
TS_ASSERT_EQUALS("int []", dataType2->getFullTypeName());
}
void test_datatype_created_with_name_and_pointer_modifier_has_pointer_modifier()
{
DataTypeQualifierList qualifierList;
DataTypeModifierStack modifierStack;
modifierStack.push(std::make_shared<DataTypeModifierPointer>());
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
TS_ASSERT_EQUALS("int *", dataType.getFullTypeName());
std::shared_ptr<DataType> dataType1 = std::make_shared<NamedDataType>(utility::splitToVector("int", "::"));
std::shared_ptr<DataType> dataType2 = std::make_shared<PointerModifiedDataType>(dataType1);
TS_ASSERT_EQUALS("int *", dataType2->getFullTypeName());
}
void test_datatype_created_with_name_and_reference_modifier_has_reference_modifier()
{
DataTypeQualifierList qualifierList;
DataTypeModifierStack modifierStack;
modifierStack.push(std::make_shared<DataTypeModifierReference>());
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
TS_ASSERT_EQUALS("int &", dataType.getFullTypeName());
std::shared_ptr<DataType> dataType1 = std::make_shared<NamedDataType>(utility::splitToVector("int", "::"));
std::shared_ptr<DataType> dataType2 = std::make_shared<ReferenceModifiedDataType>(dataType1);
TS_ASSERT_EQUALS("int &", dataType2->getFullTypeName());
}
void test_datatype_created_with_name_and_const_pointer_modifier_has_const_pointer_modifier()
{
DataTypeQualifierList qualifierList;
DataTypeModifierStack modifierStack;
std::shared_ptr<DataTypeModifier> modifier = std::make_shared<DataTypeModifierPointer>();
modifier->addQualifier(DataTypeQualifierList::QUALIFIER_CONST);
modifierStack.push(modifier);
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
TS_ASSERT_EQUALS("int * const", dataType.getFullTypeName());
std::shared_ptr<DataType> dataType1 = std::make_shared<NamedDataType>(utility::splitToVector("int", "::"));
std::shared_ptr<DataType> dataType2 = std::make_shared<PointerModifiedDataType>(dataType1);
dataType2->addQualifier(DataType::QUALIFIER_CONST);
TS_ASSERT_EQUALS("int * const", dataType2->getFullTypeName());
}
void test_datatype_created_with_name_and_pointer_pointer_modifier_has_pointer_pointer_modifier()
{
DataTypeQualifierList qualifierList;
DataTypeModifierStack modifierStack;
modifierStack.push(std::make_shared<DataTypeModifierPointer>());
modifierStack.push(std::make_shared<DataTypeModifierPointer>());
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
TS_ASSERT_EQUALS("int * *", dataType.getFullTypeName());
std::shared_ptr<DataType> dataType1 = std::make_shared<NamedDataType>(utility::splitToVector("int", "::"));
std::shared_ptr<DataType> dataType2 = std::make_shared<PointerModifiedDataType>(dataType1);
std::shared_ptr<DataType> dataType3 = std::make_shared<PointerModifiedDataType>(dataType2);
TS_ASSERT_EQUALS("int * *", dataType3->getFullTypeName());
}
};
+1 -1
View File
@@ -802,7 +802,7 @@ private:
ParseTypeUsage typeUsage(const std::string& typeName) const
{
return ParseTypeUsage(validLocation(), DataType(utility::splitToVector(typeName, "::")));
return ParseTypeUsage(validLocation(), std::make_shared<NamedDataType>(utility::splitToVector(typeName, "::")));
}
std::vector<ParseTypeUsage> parameters(const std::string& param) const