source: src/ControlStruct/FixLabels.cpp@ 5ad6f0d

Last change on this file since 5ad6f0d was b1f2007d, checked in by Peter A. Buhr <pabuhr@…>, 22 months ago

first attempt at simplifying SemanticError and its usage

  • Property mode set to 100644
File size: 3.0 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// FixLabels.cpp -- Normalizes labels and handles multi-level exit labels.
8//
9// Author : Andrew Beach
10// Created On : Mon Nov 1 09:39:00 2021
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Sun Nov 26 15:06:51 2023
13// Update Count : 10
14//
15
16#include "FixLabels.hpp"
17
18#include "AST/Label.hpp"
19#include "AST/Pass.hpp"
20#include "AST/Stmt.hpp"
21#include "ControlStruct/MultiLevelExit.hpp"
22using namespace ast;
23
24namespace ControlStruct {
25class FixLabelsCore final : public WithGuards {
26 LabelToStmt labelTable;
27 public:
28 FixLabelsCore() : labelTable() {}
29
30 void previsit( const FunctionDecl * );
31 const FunctionDecl * postvisit( const FunctionDecl * );
32 void previsit( const Stmt * );
33 void previsit( const BranchStmt * );
34 void previsit( const LabelAddressExpr * );
35
36 void setLabelsDef( const std::vector<Label> &, const Stmt * );
37 void setLabelsUsage( const Label & );
38};
39
40void FixLabelsCore::previsit( const FunctionDecl * ) {
41 GuardValue( labelTable ).clear();
42}
43
44const FunctionDecl * FixLabelsCore::postvisit(
45 const FunctionDecl * decl ) {
46 if ( nullptr == decl->stmts ) return decl;
47 for ( auto kvp : labelTable ) {
48 if ( nullptr == kvp.second ) {
49 SemanticError( kvp.first.location, "Use of undefined label %s.", kvp.first.name.c_str() );
50 }
51 }
52 return mutate_field( decl, &FunctionDecl::stmts,
53 multiLevelExitUpdate( decl->stmts.get(), labelTable ) );
54}
55
56void FixLabelsCore::previsit( const Stmt * stmt ) {
57 if ( !stmt->labels.empty() ) {
58 setLabelsDef( stmt->labels, stmt );
59 }
60}
61
62void FixLabelsCore::previsit( const BranchStmt * stmt ) {
63 if ( !stmt->labels.empty() ) {
64 setLabelsDef( stmt->labels, stmt );
65 }
66 if ( !stmt->target.empty() ) {
67 setLabelsUsage( stmt->target );
68 }
69}
70
71void FixLabelsCore::previsit( const LabelAddressExpr * expr ) {
72 assert( !expr->arg.empty() );
73 setLabelsUsage( expr->arg );
74}
75
76void FixLabelsCore::setLabelsDef(
77 const std::vector<Label> & labels, const Stmt * stmt ) {
78 assert( !labels.empty() );
79 assert( stmt );
80
81 for ( auto label : labels ) {
82 if ( labelTable.find( label ) == labelTable.end() ) {
83 // Make sure to only create the entry once.
84 labelTable[ label ] = stmt;
85 } else if ( nullptr != labelTable[ label ] ) {
86 // Duplicate definition, this is an error.
87 SemanticError( label.location,
88 "Duplicate definition of label: " + label.name );
89 } else {
90 // Perviously used, but not defined until now.
91 labelTable[ label ] = stmt;
92 }
93 }
94}
95
96// Label was used, if it is new add it to the table.
97void FixLabelsCore::setLabelsUsage( const Label & label ) {
98 if ( labelTable.find( label ) == labelTable.end() ) {
99 labelTable[ label ] = nullptr;
100 }
101}
102
103void fixLabels( TranslationUnit & translationUnit ) {
104 Pass<FixLabelsCore>::run( translationUnit );
105}
106} // namespace ControlStruct
107
108// Local Variables: //
109// tab-width: 4 //
110// mode: c++ //
111// compile-command: "make install" //
112// End: //
Note: See TracBrowser for help on using the repository browser.