]> granicus.if.org Git - clang/commitdiff
Some enhancements to DeclStmt printing. Some of this should
authorEli Friedman <eli.friedman@gmail.com>
Sat, 30 May 2009 00:19:54 +0000 (00:19 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sat, 30 May 2009 00:19:54 +0000 (00:19 +0000)
move to DeclPrinter.cpp, but I haven't quite worked out how best to do
that.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72599 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/StmtPrinter.cpp

index fc9fdf975d0a404091a7c24b5dff750afcc7c86e..7fe1524c58c49a68e856027191e5bf10edc287db 100644 (file)
@@ -56,11 +56,15 @@ namespace  {
       }
       IndentLevel -= SubIndent;
     }
-    
+
+    QualType GetBaseType(QualType T);
+    void PrintBaseType(QualType T, TagDecl* TD);
+    void PrintDeclIdentifier(NamedDecl* ND);
     void PrintRawCompoundStmt(CompoundStmt *S);
     void PrintRawDecl(Decl *D);
     void PrintRawDeclStmt(DeclStmt *S);
     void PrintFieldDecl(FieldDecl *FD);
+    void PrintEnumConstantDecl(EnumConstantDecl *ECD);
     void PrintRawIfStmt(IfStmt *If);
     void PrintRawCXXCatchStmt(CXXCatchStmt *Catch);
     
@@ -112,6 +116,57 @@ void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) {
   Indent() << "}";
 }
 
+QualType StmtPrinter::GetBaseType(QualType T) {
+  // FIXME: This should be on the Type class!
+  QualType BaseType = T;
+  while (!BaseType->isSpecifierType()) {
+    if (isa<TypedefType>(BaseType))
+      break;
+    else if (const PointerType* PTy = BaseType->getAsPointerType())
+      BaseType = PTy->getPointeeType();
+    else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
+      BaseType = ATy->getElementType();
+    else if (const FunctionType* FTy = BaseType->getAsFunctionType())
+      BaseType = FTy->getResultType();
+    else
+      assert(0 && "Unknown declarator!");
+  }
+  return BaseType;
+}
+
+void StmtPrinter::PrintBaseType(QualType BaseType, TagDecl* TD) {
+  std::string BaseString;
+  if (TD && TD->isDefinition()) {
+    // FIXME: This is an ugly hack; perhaps we can expose something better
+    // from Type.h?
+    if (BaseType.isConstQualified())
+      OS << "const ";
+    PrintRawDecl(TD);
+    OS << " ";
+  } else {
+    BaseType.getAsStringInternal(BaseString, Policy);
+    OS << BaseString << " ";
+  }
+}
+
+void StmtPrinter::PrintDeclIdentifier(NamedDecl* ND) {
+  std::string Name = ND->getNameAsString();
+
+  QualType Ty;
+  if (TypedefDecl* TDD = dyn_cast<TypedefDecl>(ND)) {
+    Ty = TDD->getUnderlyingType();
+  } else if (ValueDecl* VD = dyn_cast<ValueDecl>(ND)) {
+    Ty = VD->getType();
+  } else {
+    assert(0 && "Unexpected decl");
+  }
+
+  PrintingPolicy SubPolicy(Policy);
+  SubPolicy.SuppressTypeSpecifiers = true;
+  Ty.getAsStringInternal(Name, SubPolicy);
+  OS << Name;
+}
+
 void StmtPrinter::PrintRawDecl(Decl *D) {
   // FIXME: Need to complete/beautify this... this code simply shows the
   // nodes are where they need to be.
@@ -143,16 +198,28 @@ void StmtPrinter::PrintRawDecl(Decl *D) {
     OS << " ";
     if (const IdentifierInfo *II = TD->getIdentifier())
       OS << II->getName();
-    if (RecordDecl *RD = dyn_cast<RecordDecl>(TD)) {
-      OS << "{\n";
-      IndentLevel += 1;
-      // FIXME: The context passed to field_begin/field_end should
-      // never be NULL!
-      ASTContext *Context = 0;
-      for (RecordDecl::field_iterator i = RD->field_begin(*Context);
-           i != RD->field_end(*Context); ++i) {
-        PrintFieldDecl(*i);
-      IndentLevel -= 1;
+    if (TD->isDefinition()) {
+      if (RecordDecl *RD = dyn_cast<RecordDecl>(TD)) {
+        OS << "{\n";
+        IndentLevel += 1;
+        // FIXME: The context passed to field_begin/field_end should
+        // never be NULL!
+        ASTContext *Context = 0;
+        for (RecordDecl::field_iterator i = RD->field_begin(*Context);
+             i != RD->field_end(*Context); ++i)
+          PrintFieldDecl(*i);
+        IndentLevel -= 1;
+        Indent() << "}";
+      } else if (EnumDecl *ED = dyn_cast<EnumDecl>(TD)) {
+        OS << "{\n";
+        IndentLevel += 1;
+        // FIXME: The context shouldn't be NULL!
+        ASTContext *Context = 0;
+        for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Context);
+             i != ED->enumerator_end(*Context); ++i)
+          PrintEnumConstantDecl(*i);
+        IndentLevel -= 1;
+        Indent() << "}";
       }
     }
   } else {
@@ -161,19 +228,72 @@ void StmtPrinter::PrintRawDecl(Decl *D) {
 }
 
 void StmtPrinter::PrintFieldDecl(FieldDecl *FD) {
-  Indent() << FD->getNameAsString() << "\n";
+  Indent();
+  QualType BaseType = GetBaseType(FD->getType());
+  PrintBaseType(BaseType, 0);
+  PrintDeclIdentifier(FD);
+  if (FD->isBitField()) {
+    OS << " : ";
+    PrintExpr(FD->getBitWidth());
+  }
+  OS << ";\n";
+}
+
+void StmtPrinter::PrintEnumConstantDecl(EnumConstantDecl *ECD) {
+  Indent() << ECD->getNameAsString();
+  if (ECD->getInitExpr()) {
+    OS << " = ";
+    PrintExpr(ECD->getInitExpr());
+  }
+  OS << ",\n";
 }
 
 void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) {
+  DeclStmt::decl_iterator Begin = S->decl_begin(), End = S->decl_end();
+
+  TagDecl* TD = dyn_cast<TagDecl>(*Begin);
+  if (TD)
+    ++Begin;
+
+  if (isa<TypedefDecl>(*Begin))
+    OS << "typedef ";
+  else if (VarDecl *V = dyn_cast<VarDecl>(*Begin)) {
+    switch (V->getStorageClass()) {
+    default: assert(0 && "Unknown storage class!");
+    case VarDecl::None:          break;
+    case VarDecl::Auto:          OS << "auto "; break;
+    case VarDecl::Register:      OS << "register "; break;
+    case VarDecl::Extern:        OS << "extern "; break;
+    case VarDecl::Static:        OS << "static "; break; 
+    case VarDecl::PrivateExtern: OS << "__private_extern__ "; break; 
+    }
+  } else if (FunctionDecl *V = dyn_cast<FunctionDecl>(*Begin)) {
+    switch (V->getStorageClass()) {
+    default: assert(0 && "Unknown storage class!");
+    case FunctionDecl::None:          break;
+    case FunctionDecl::Extern:        OS << "extern "; break;
+    case FunctionDecl::Static:        OS << "static "; break; 
+    case FunctionDecl::PrivateExtern: OS << "__private_extern__ "; break; 
+    }
+  } else {
+    assert(0 && "Unhandled decl");
+  }
+
+  QualType BaseType;
+  if (ValueDecl* VD = dyn_cast<ValueDecl>(*Begin)) {
+    BaseType = VD->getType();
+  } else {
+    BaseType = cast<TypedefDecl>(*Begin)->getUnderlyingType();
+  }
+  BaseType = GetBaseType(BaseType);
+  PrintBaseType(BaseType, TD);
+
   bool isFirst = true;
-  
-  for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();
-       I != E; ++I) {
-    
+  for ( ; Begin != End; ++Begin) {
     if (!isFirst) OS << ", ";
     else isFirst = false;
-    
-    PrintRawDecl(*I);
+
+    PrintDeclIdentifier(cast<NamedDecl>(*Begin));
   }
 }
 
@@ -182,12 +302,9 @@ void StmtPrinter::VisitNullStmt(NullStmt *Node) {
 }
 
 void StmtPrinter::VisitDeclStmt(DeclStmt *Node) {
-  for (DeclStmt::decl_iterator I = Node->decl_begin(), E = Node->decl_end();
-       I!=E; ++I) {    
-    Indent();
-    PrintRawDecl(*I);
-    OS << ";\n";
-  }
+  Indent();
+  PrintRawDeclStmt(Node);
+  OS << ";\n";
 }
 
 void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) {